POJ 1703 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.

題解

這個題目有點繞

#include<cstdio>
#include<cstring>
const int MAX = 1000000;
//將有聯繫的人放到同一個集合裏面,不管是不是同一團伙,只要有聯繫就放到同一集合
//然後用rela數組區分同一集合內是不是同一團伙
int father[MAX];//並查集數組
//int count;//集合的個數
int rela[MAX];//rela[i]表示i與其父親結點的關係,0表示同一團伙,1表示不同團伙
void init_set(int n){
   for(int i=1;i<=n;i++){father[i] = i;rela[i]=0;}
}
int find(int x){
  int tmp = father[x];
  if(x == father[x])
     return x;
  father[x] = find(father[x]);
  //因爲最上層也就是根節點的父親一定是同一團伙的,也就是rela一定爲0
  //如果x與其未更新前的父親屬於同一團伙,則rela爲0
  //如果x與其未更新前的父親屬於不同團伙,則rela爲1
  //如果rela[x]!=rela[tmp]則說明x的父親沒有掛到別的集合
  rela[x] = (rela[x] == rela[tmp]) ? 0 : 1;
  return father[x];
}
void unin(int x,int y){
  int fx = find(x);
  int fy = find(y);
  father[fx] = fy;
  //
  //如果rela[x]==0&&rela[y]==1則朋友的  敵人的敵人  就是我的朋友
  //如果rela[x]==0&&rela[y]==0則朋友的  敵人的朋友  就是我的敵人
  //如果rela[x]==1&&rela[y]==0則敵人的  敵人的朋友  就是我的朋友
  //如果rela[x]==1&&rela[y]==1則敵人的  敵人的敵人  就是我的敵人
  rela[fx] = (rela[x] == rela[y]) ? 1 : 0;
}
int main(){
  int T,N,M;
  scanf("%d",&T);
  while(~scanf("%d%d",&N,&M)){
    init_set(N);
    char s[5];
    int l,r;
    for(int i=0;i<M;i++){
       scanf("%s%d%d",s,&l,&r);
       if(strcmp(s,"D")==0){
           unin(l,r);
       }else{
           int x = find(l);
           int y = find(r);
           if(x!=y){
             printf("Not sure yet.\n");
           }else{
              if(rela[l]==rela[r]){
                 printf("In the same gang.\n");
              }else{
                 printf("In different gangs.\n");
              }
           }
       }
    }
  }
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章