poj find them,catch them 並查集

題目:

Description

The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.) 

Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds: 

1. D [a] [b] 
where [a] and [b] are the numbers of two criminals, and they belong to different gangs. 

2. A [a] [b] 
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang. 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

Sample Input

1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

Sample Output

Not sure yet.
In different gangs.
In the same gang.

花了一些力氣,終於把這個經典的題弄懂了,感謝TR學長的解答。

在這之前先拿一道經典的題拋磚引玉:

有N個人,M個關係,每個關係由a, b, c三個量描述,表示a與b的關係是c。當c爲0時表示a,b是朋友,當c爲1時表示a, b是敵人。已知關係具有傳遞性,也就是說a, b是朋友以及a, d是朋友的時候b, d是朋友。a, b是敵人以及a, d是朋友的時候b, d是敵人。問題給的M條關係是否成立,若成立則輸出"YES",否則輸出"NO",並輸出最早在給出第幾條關係的時候可以確定關係不成立。
(N, M <= 10^5, a, b <= N, a != b, c = 0, 1)


大概就是說:如果讓並查集維護朋友關係是很簡單的,a,b是朋友,b,c是朋友,用並查集的unit操作+find詢問,很容易知道a,c是朋友,但是我該怎麼維護敵人關係。我們考慮引入輔助元素,例如i是它本尊,i+N是它的宿敵。當然這個宿敵是不存在的,是我們虛擬出來的。

a,b是敵人的話,那麼unit(a,b+N),unit(b,a+N),爲什麼?如果a和b的宿敵是朋友,那麼a和b就是敵人了。記住,並查集永遠只維護朋友關係。

a,b是朋友的話:同理,我就unit(a,b),unit(a+N,b+N)。

怎樣判斷信息是錯誤的?如果a和a的宿敵當朋友了,換句話說,就是與前面的信息矛盾了,就說明信息是錯的。

這題自己的code:

#include<cstdio>
const int MAXN=1e5+5;
int par[2*MAXN];
int find(int x){
    return par[x]==x?par[x]:find(par[x]);
}
void unit(int x,int y){
    x=find(x);y=find(y);
    if(x!=y)par[x]=y;
}
int main(){
    int N,M;scanf("%d%d",&N,&M);
    for(int i=0;i<2*N;++i)
        par[i]=i;
    int i;
    for(i=0;i<M;++i){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        if(c==0){
            if(find(a)==find(b+N)||(find(a+N)==find(b)))break;
            unit(a,b);
            unit(a+N,b+N);
        }
        if(c==1){
            if(find(a)==find(b)||find(a+N)==find(b+N))break;
            unit(a,b+N);
            unit(a+N,b);
        }
    }
    printf("%d\n",i+1);
}

好了,如果上面的理解清楚了,那麼這個題就不難了。

code:

#include<cstdio>
const int MAXN=1e5+5;
int par[MAXN*2];
int find(int x){
    return par[x]==x?par[x]:par[x]=find(par[x]);
}
void unite(int x,int y){
    x=find(x);y=find(y);
    if(x!=y)par[x]=y;
}
int main(void){
    int T;scanf("%d",&T);
    while(T--){
        int N,M;scanf("%d%d",&N,&M);getchar();
        for(int i=0;i<2*N;++i)
            par[i]=i;
        for(int i=0;i<M;++i){
            char ch;int a,b;
            scanf("%c%d%d",&ch,&a,&b);getchar();
            if(ch=='A'){
                if(find(a)==find(b))printf("In the same gang.\n");
                else if(find(a)==find(N+b))printf("In different gangs.\n");
                else printf("Not sure yet.\n");
            }else{
                unite(a,b+N);
                unite(a+N,b);
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章