ZJNU 1333 - 第二题 blocks--中高级

因为放一个就需要判断一次,每一次跑一遍全图bfs显然是不现实的

又因为点只有三种,黑白无

所以可以用并查集优化

添加一个棋子就判断周围四个的组别情况

注意出现的情况与答案关系之间的判别

#include<stdio.h>
#include<memory.h>
int N,M,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},gp[250010];
char cm[505][505];
int findp(int p){
    return p==gp[p]?p:(gp[p]=findp(gp[p]));
}
int prime(int x,int y){
    return x>=0&&y>=0&&x<N&&y<N;
}
int main(){
    int i,j,X,Y,xx,yy,ans=0,g,d1,d2;
    char C;
    memset(cm,'.',sizeof cm);
    for(i=0;i<250000;i++)
        gp[i]=i;
    scanf("%d%d",&N,&M);
    for(i=0;i<M;i++){
        scanf("%*c%c%d%d",&C,&X,&Y);
        ans++;
        for(g=j=0;j<4;j++){
            xx=X-1+dx[j];
            yy=Y-1+dy[j];
            if(prime(xx,yy)&&cm[xx][yy]==C){
                d1=findp(gp[(X-1)*N+(Y-1)]);
                d2=findp(gp[xx*N+yy]);
                if(!g){//周围4个位置如果还没有找到一个同集合的,可以直接合并并减少一个答案组
                    g=1;
                    if(d1!=d2){
                        if(d1<d2)
                            gp[d2]=d1;
                        else
                            gp[d1]=d2;
                    }
                    ans--;
                }
                else{//周围4个位置如果已经找到一个同组的了,只有两个点所在的集合不同时才需要合并并减少一个答案组
                    if(d1!=d2){
                        if(d1<d2)
                            gp[d2]=d1;
                        else
                            gp[d1]=d2;
                        ans--;
                    }
                }
            }
        }
        cm[X-1][Y-1]=C;
        printf("%d\n",ans);
    }
    
    return 0;
}

 

posted @ 2020-01-26 22:08  StelaYuri  阅读(124)  评论(0)    收藏  举报