HDU 5652 India and China Origins 并查集

分析:这是一个连通性的问题。你会发现如果将所有操作逆序来看的话就很容易用并查集来处理了。 首先把所有的山峰都加到图中,然后逆序处理每个操作:

对某次操作,在图中删除该位置的山峰,然后判断两个点是否联通,一旦联通就得到了结果。 这里需要对China和India分别新建一个对应的节点。

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=1e3+5;
const int INF=0x3f3f3f3f;
char s[N][N];
struct Que
{
    int x,y;
} p[N*N];
int dx[4]= {0,0,-1,1};
int dy[4]= {-1,1,0,0};
int fa[N*N],r[N*N];
int find(int x)
{
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}
void fun(int x,int y)
{
    x=find(x),y=find(y);
    if(x!=y)
    {
        if(r[x]>r[y])
        {
            fa[y]=x;
        }
        else if(r[x]<r[y])
        {
            fa[x]=y;
        }
        else fa[y]=x,++r[x];
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,q;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; ++i)
            scanf("%s",s[i]+1);
        scanf("%d",&q);
        for(int i=1; i<=q; ++i)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            ++p[i].x,++p[i].y;
            s[p[i].x][p[i].y]='1';
        }
        for(int i=1; i<=n*m+2; ++i)fa[i]=i,r[i]=0;
        int k1=n*m+1,k2=n*m+2;
        for(int i=1; i<=m; ++i)
        {
            if(s[1][i]=='0')fun(k1,i);
            if(s[n][i]=='0')fun(k2,(n-1)*m+i);
        }
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=m; ++j)
            {
                if(s[i][j]=='1')continue;
                if(i<n&&s[i+1][j]=='0')fun((i-1)*m+j,i*m+j);
                if(j<m&&s[i][j+1]=='0')fun((i-1)*m+j,(i-1)*m+j+1);
            }
        }
        if(find(k1)==find(k2))
        {
            printf("-1\n");
            continue;
        }
        int ans=0;
        for(int i=q; i>0; --i)
        {
            int x=p[i].x,y=p[i].y;
            s[x][y]='0';
            if(x==1)fun(k1,y);
            if(x==n)fun(k2,(n-1)*m+y);
            for(int j=0; j<4; ++j)
            {
                int xx=x+dx[j];
                int yy=y+dy[j];
                if(xx<1||xx>n||yy<1||yy>m)continue;
                if(s[xx][yy]=='1')continue;
                fun((x-1)*m+y,(xx-1)*m+yy);
            }
            if(find(k1)==find(k2))
            {
                ans=i;
                break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2016-03-26 22:01  shuguangzw  阅读(374)  评论(0编辑  收藏  举报