刷題——Find them, Catch them POJ - 1703

/*
有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章