• 3.31考试T2


    题目描述

    有一个(n*m)的地图,把左边界和右边界粘起来使得形成一个圆柱,现在要不断地挖去其中的格子,要求任何时候都存在一条从最上方到最下方的路径(四联通),如果某次操作不满足要求则不做,问最后有多少次操作是成功的。

    题解

    从上到下四联通可以转化成从左到右删去的点不能够八联通,考虑怎么判断是否八联通。

    首先我们将地图复制一遍,左边一份,右边一份,每次在左边和右边依次加入删去的点,然后我们对于删去的点进行维护。

    我们使用并查集维护联通块,每个点的(fa)代表它所在的联通块中删去最早的点。

    如果加入的两个点所在的联通块相同的话,由于这两个点本质上又是一个点,所以就形成了从左到右的八联通通道。

    注意:额外判断(m=1)时,加入任何一个点肯定会导致从左到右删去的点能够八联通。

    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    const int N = 6e5 + 5;
    int n, m, Q, ans, fa[N], cnt, vis[3005][6005], pos[N];
    int nx[10] = {0, 0, 0, 1, 1, 1, -1, -1, -1};
    int ny[10] = {0, 1, -1, 0, 1, -1, 0, 1, -1};
    inline int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    int find(int x) {return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);}
    int way(int x, int y)
    {
    	if(m == 1) return 0; int u, v; cnt ++;
    	for(int k = 1; k <= 2; k ++)
    	{
    		if(k == 1) u = x, v = y; else u = x, v = y + m;
    		for(int i = 1; i <= 8; i ++)
    		{
    			int uu = u + nx[i], vv = v + ny[i];
    			if(uu < 1 || uu > n) continue;
    			if(vv > 2 * m) vv -= 2 * m; else if(vv <= 0) vv += 2 * m;
    			if(vis[uu][vv])
    			{
    				if(k == 1) pos[find(vis[uu][vv])] = cnt;
    				else if(pos[find(vis[uu][vv])] == cnt) return 0;
    			}
    		}
    	}
    	return 1;
    }
    int main()
    {
    	n = read(); m = read(); Q = read(); int x, y;
    	for(int i = 1; i <= 2 * Q; i ++) fa[i] = i;
    	for(int num = 1, u, v; num <= Q; num ++)
    	{
    		x = read(); y = read();
    		if(way(x, y))
    		{
    			vis[x][y] = num; vis[x][y + m] = num + Q;
    			for(int k = 1; k <= 2; k ++)
    			{
    				if(k == 1) u = x, v = y; else u = x, v = y + m;
    				for(int i = 1; i <= 8; i ++)
    				{
    					int uu = u + nx[i], vv = v + ny[i];
    					if(uu < 1 || uu > n) continue;
    					if(vv > 2 * m) vv -= 2 * m; else if(vv <= 0) vv += 2 * m;
    					if(vis[uu][vv]) fa[find(vis[u][v])] = find(vis[uu][vv]);
    				}
    			}
    			ans ++;
    		}
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    sharepoint2010无法连接到配置数据库。
    多选框加和单选框一样的控制,只能选一个
    Windows Server 2008 网站访问PHP响应慢的解决方法
    Windows下的PHP安装文件线程安全和非线程安全的区别
    Apache+PHP 环境上传文件配置
    出现 HTTP Error 503. The service is unavailable 错误
    IIS7 上传 下载文件大小限制的设置
    php 错误信息配置
    新篇章
    面向对象
  • 原文地址:https://www.cnblogs.com/Sunny-r/p/12606637.html
Copyright © 2020-2023  润新知