【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