HDU 4775 Infinite Go 并查集+模拟

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4775

题意:在一个只有左和上边界的棋盘上下围棋,如果被围死就被吃掉,求最后黑色和白色棋子的个数

 

我们可以利用并查集来保存连通块,同时维护这个连通块周围的空格数,如果空格数为0,则删去这个连通块,同时返还给其他连通块空格数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define p make_pair
using namespace std;
const int N=1e4+5;
map<pair<int,int>,int> ma;
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int f[N],fre[N];//父节点和空格数目
int cnt[2];//棋子数目
int Find(int x)
{
    return f[x]==x?x:f[x]=Find(f[x]);
}
int check(int x,int y)//判断是否为空格
{
    if (x==0||y==0) return 0;
    if (ma.find(p(x,y))==ma.end()) return 1;
    int t=ma[p(x,y)];
    fre[Find(t)]--;
    return 0;
}
void hb(int x,int y,int xx,int yy)//合并连通块
{
    if (x==0||y==0) return;
    if (ma.find(p(xx,yy))==ma.end()) return;
    int t=ma[p(x,y)];
    int ft=Find(t);
    int tt=ma[p(xx,yy)];
    int ftt=Find(tt);
    if (ft!=ftt)
        if (t%2==tt%2)
    {
        fre[ft]+=fre[ftt];
        f[ftt]=ft;
    }
}
void Clear(int x,int y,int col)//清除连通块
{
    if (x==0||y==0) return;
    if (ma.find(p(x,y))==ma.end()) return;
    int t=ma[p(x,y)];
    if (t%2!=col)
    {
        fre[Find(t)]++;
        return;
    }
    cnt[col]--;
    ma.erase(p(x,y));
    for(int i=0;i<4;i++)
        Clear(x+fx[i],y+fy[i],col);
}
void xc(int x,int y,int col)//判断是否需要消除
{
    if (x==0||y==0) return;
    if (ma.find(p(x,y))==ma.end()) return;
    int t=ma[p(x,y)];
    if (t%2!=col) return;
    if (fre[Find(t)]==0) Clear(x,y,col);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cnt[0]=cnt[1]=0;
        ma.clear();
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            f[i]=i;
            fre[i]=0;
        }
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            cnt[i&1]++;
            ma[p(x,y)]=i;
            for(int j=0;j<4;j++)
                fre[i]+=check(x+fx[j],y+fy[j]);
            for(int j=0;j<4;j++)
                hb(x,y,x+fx[j],y+fy[j]);
            for(int j=0;j<4;j++)
                xc(x+fx[j],y+fy[j],(i&1)^1);
            xc(x,y,i&1);
        }
        printf("%d %d\n",cnt[1],cnt[0]);
    }
    return 0;
}

  

posted @ 2017-08-29 21:15  BK_201  阅读(166)  评论(0编辑  收藏  举报