【HDOJ 5652】 India and China Origins(并查集)


1 4 6 011010 000010 100001 001000 7 0 3 1 5 1 3 0 0 1 2 2 4 2 1
4
题目大意:许多多年前,中国和印第安是相连接的……恕我地理不好……。。
之间有一些山 其余为平原
地图以1 0表示
1为山脉 0为平原
中国在最上方(横坐标为0
中国在最下方(横坐标为n-1
每个点可以向上下左右四个方向走
有q年地壳运动,每年会增加一座山(以坐标表示<x,y>)
问中国与印第安最早断开连接的年代
思路是离线处理。
存下每年地壳活动的坐标。
从第一年到最后一年把所有出现的山脉在地图上标记出。然后把能相到达的平原合并
然后从最后一年到第一年开始"拆山" 然后找到第一次两国可以相同的时间
这个时间+1就是第一次断开的年代
那么最后一个问题就是求两国此时此刻是否连通。
我的做法是枚举行为n-1(印第安)的所有平原 跑并查集看是否缩到某个行为0(中国)的点上
只要在缩点的时候缩到下标小的点上就行。
注意进行压缩的时候每次压缩玩要重新Find.否则原本的根一定是新根 会出错(在这里卡了老久……
代码如下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;
Pr pr[266666];
int pre[266666];
int dirx[] = { 0, 0,-1, 1};
int diry[] = { 1,-1, 0, 0};
char mp[555][555];
int tp;
void init(int n)
{
	for(int i = 0; i <= n; ++i) pre[i] = i;
}
int Find(int x)
{
	return pre[x] == x? pre[x]: (pre[x] = Find(pre[x]));
}
int n,m;
bool cal()
{
	for(int i = 0; i < m; ++i)
	{
		//printf("%d:%d %d:%d\n",i,Find(i),j,Find((n-1)*m+j));
		if(Find((n-1)*m+i) < m) return 1;
	}
	return 0;
}
int main()
{
	//fread();
	//fwrite();
	int t;
	int q,k,r;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i = 0; i < n; ++i)
			scanf("%s",mp[i]);
		init((n-1)*m+m-1);
		scanf("%d",&q);
		for(int i = 0; i < q; ++i)
		{
			scanf("%d%d",&pr[i].first,&pr[i].second);
			mp[pr[i].first][pr[i].second]++;
		}
	//	for(int i = 0; i < n; ++i)
	//		for(int j = 0; j < m; ++j)
	//		{
	//			printf("pre[%d](%d,%d):%d\n",i*m+j,i,j,pre[i*m+j]);
	//		}
		
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < m; ++j)
			{
				if(mp[i][j] != '0') continue;
				k = Find(i*m+j);
				if(j+1 < m && mp[i][j+1] == '0')
				{
					r = Find(i*m+j+1);
					if(k < r) pre[r] = k;
					else pre[k] = r;
				}
				k = Find(i*m+j);
				if(i+1 < n && mp[i+1][j] == '0')
				{
					r = Find((i+1)*m+j);
					if(k < r) pre[r] = k;
					else pre[k] = r;
				}
			}
		int id = -2;
	//	for(int i = 0; i < n; ++i)
	//		puts(mp[i]);
	//	for(int i = 0; i < n; ++i)
	//		for(int j = 0; j < m; ++j)
	//		{
	//			printf("pre[%d](%d,%d):%d\n",i*m+j,i,j,pre[i*m+j]);
	//		}
		if(cal()) id = -1;
		int x,y,xx,yy;
		for(int i = q-1; i >= 0 && id == -2; --i)
		{
			x = pr[i].first;
			y = pr[i].second;
			mp[x][y]--;
			if(mp[x][y] == '0')
			{
				k = Find(x*m+y);
				for(int j = 0; j < 4; ++j)
				{
					xx = x+dirx[j];
					yy = y+diry[j];
					if(0 <= xx && xx < n && 0 <= yy && yy < m && mp[xx][yy] == '0')
					{
						r = Find(xx*m+yy);
						if(k < r) pre[r] = k;
						else pre[k] = r;
						k = Find(x*m+y);
					}
				}
				if(cal()) id = i+1;
			}
		}
		printf("%d\n",id == -2? 0: id);
	}
	return 0;
}
【HDOJ 5652】 India and China Origins(并查集)
原文:http://blog.csdn.net/challengerrumble/article/details/51000789