刷题——Find them, Catch them POJ

来源:互联网 发布:淘宝美工都需要做什么 编辑:程序博客网 时间:2024/05/17 06:10
/*
有n个人这n个人来自与两个帮派,现在有两种操作
D a b,a b不属于一个帮派
A a b,a b的关系,是同一个帮派,还是不同的,还是不确定
用一个数组来确定是否有联系rt[],再用一个数组来存放有联系人处于那个帮派gan[]


他们之间的联系,就跟平常所用的并查集一样,最主要的是在有联系的人上
先将所处的帮派全部设为1,(01两个帮派)
这样子每一个关系带的头都是1
假设a b处在不同帮派
将a的头连入b的头,那么gan[a]=(gan[a]+gan[b])%2
若a,b的gan相同,那么a原先所处的帮派全部变换0->1,1->0
若a,b的gan不同那么a和b原先所属的gan不用变换


变换的过程若头两个为1,1就是说gan不用更新
连续的gan会出现两种种情况:1,1(现头,原头);1,0(原头,原子)
gan[x]=(gan[x](子节点)+gan[temp](父节点)+1)%2 (1+1+1)%2=1;(0+1+1)%2=0;


变换的过程若头两个为1,0就是说gan要更新
连续的gan会出现两种种情况:1,0(现头,原头);0,0(原头,原子)
gan[x]=(gan[x]+gan[temp]+1)%2 (1+1+1)%2=1;(0+0+1)%2=0;


更新的过程子都连接到头了
*/
#include <stdio.h>
int rt[100010];
int gan[100010];
int find(int x)
{
    if(rt[x]==x){
        return rt[x];
    }
    int temp=rt[x];
    rt[x]=find(rt[x]);
    gan[x]=(gan[x]+gan[temp]+1)%2;
    return rt[x];
}
void un(int x,int y){
    int a=find(x);
    int b=find(y);
    if(a!=b){
        rt[a]=b;
        gan[a]=(gan[x]+gan[y])%2;
    }
}
int main(){
    int t,n,m,a,b;
    char op[2];
    scanf("%d",&t);
    while(t--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++){
            rt[i]=i;
            gan[i]=1;
        }
        for(int i=0;i<m;i++){
            scanf("%s %d %d",op,&a,&b);
            if(op[0]=='D'){
                un(a,b);
            }
            else{
                if(find(a)!=find(b)){
                    printf("Not sure yet.\n");
                }
                else{
                    if(gan[a]==gan[b]){
                        printf("In the same gang.\n");
                    }
                    else{
                        printf("In different gangs.\n");
                    }
                }
            }
        }
    }
    return 0;
}