POJ1703 Find them, Catch them(並查集)

題目連接:http://poj.org/problem?id=1703node

塔都市的警察局決定以混亂爲目標,做爲啓動行動,紮根城市中的兩個幫派,Gang Dragon和Gang Snake。
可是,警方首先須要肯定犯罪分子屬於哪一個團伙。目前的問題是,兩名罪犯; 他們屬於同一個氏族嗎?
您必須根據不完整的信息作出判斷。(由於歹徒老是暗中行動。)
假設N(N <= 10 ^ 5)罪犯目前在塔都市,編號從1到N.固然,他們中至少有一人屬於Gang Dragon,
一樣爲Gang Snake。您將按順序給出M(M <= 10 ^ 5)個消息,它們分爲如下兩種:
1。D [a] [b]
其中[a]和[b]是兩個罪犯的數字,以及他們屬於不一樣的幫派。
2. A [a] [b]
其中[a]和[b]是兩個罪犯的數量。這須要您決定a和b是否屬於同一個團伙。
輸入
輸入的第一行包含單個整數T(1 <= T <= 20),即測試用例的數量。而後是T案例。
每一個測試用例以具備兩個整數N和M的行開始,接着是M行,每行包含如上所述的一個消息。
產量
對於每種狀況下的每條消息「A [a] [b]」,您的程序應根據以前得到的信息進行判斷。
樣本輸入
1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4
樣本輸出
Not sure yet.
In different gangs.
In the same gang.
這個題目也是典型的並查集的題目,由於總共只有兩個黑幫,因此能夠用兩個集合來求解。當讓,用一個集合也能夠。
只是要對relation進行細心設置(能夠設置relatiin:0表示關係相同,1爲關係不一樣)。在對一個元素執行Find()操做時,若是它與父親結點realtion相同,父親結點與根結點relation相同,那麼該元素與根結點關係也相同。不然是不一樣的。
 1 int DisJoinSet ::Find(int x)
 2 {
 3     int temp = tree[x].parent;//temp x的父親結點
 4     if(x != tree[x].parent)
 5     {
 6         tree[x].parent = Find(tree[x].parent);//遞歸在雙親中找x
 7     // tree[temp].relation必爲temp結點(x的父節點)與根節點的關係,tree[x].relation最初爲x與temp的關係,
 8     // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同爲1,或者同爲0
 9     // 若是tree[x].relation和tree[temp].relation同爲1,意味着根節點與temp不一樣類,temp與x不一樣類,總共只有2個集合,x與根節點一定同類。
10     // 若是tree[x].relation和tree[temp].relation同爲0,意味着根節點與temp同類,temp與x同類,x與根節點也一定同類。
11         if(tree[x].relation == tree[temp].relation)
12         {
13             tree[x].relation = 0;
14         }
15     // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一個爲1,一個爲0,
16     // 若是tree[temp].relation爲false,tree[temp].relation爲1,意味着根節點和temp同類,temp與x不一樣類,那麼x與根節點必然不一樣類
17     // 若是tree[temp].relation爲true,tree[x].relation爲0,意味着根節點和temp不一樣類,temp與x同類,那麼x與根節點必然不一樣類
18         else
19         {
20             tree[x].relation = 1;
21         }    
22         return tree[x].parent;// 返回根節點下標
23     }
24     else
25     {
26         return x;
27     }
28 }
View Code
在進行合併操做時,由於合併的x和y是屬於不一樣集合的,因此和上面同樣的推理。
 1 void DisJoinSet ::Union(int x,int y)
 2 {
 3     int rootx = Find(x);
 4     int rooty = Find(y);
 5     if(rootx == rooty)
 6     {
 7         return ;
 8     }
 9     if(tree[rootx].rank > tree[rooty].rank)
10     {
11         tree[rooty].parent = rootx;
12         // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty
13         // 若是tree[x].relation和tree[y].relation均爲1,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類;
14         // 若是tree[x].relation和tree[y].relation均爲0,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類
15         if(tree[x].relation == tree[y].relation)
16         {
17             tree[rooty].relation = 1;
18         }
19         // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類;
20         // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類;
21         else
22         {
23             tree[rooty].relation = 0;
24         }
25     }
26     else
27     {
28         tree[rootx].parent = rooty;
29         if(tree[rootx].rank == tree[rooty].rank)
30         {
31             tree[rooty].rank ++;
32         }
33         // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty
34         // 若是relation[x]和relation[y]均爲true,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類;
35         // 若是relation[x]和relation[y]均爲false,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類
36         if(tree[x].relation == tree[y].relation)
37         {
38             tree[rootx].relation = 1;
39         }
40         // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類;
41         // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類;
42         else
43         {
44             tree[rootx].relation = 0;
45         }
46     }
47 }
View Code

完整代碼:ios

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<vector>
  6 #include<stack>
  7 #include<map>
  8 #include<set>
  9 #include<list>
 10 #include<queue>
 11 #include<string>
 12 #include<algorithm>
 13 #include<iomanip>
 14 using namespace std;
 15 
 16 struct node
 17 {
 18     int no;
 19     int rank;
 20     int parent;
 21     int relation;
 22 };
 23 
 24 class DisJoinSet
 25 {
 26     protected:
 27         int n;
 28         node *tree;
 29     public :
 30         DisJoinSet(int n);
 31         ~DisJoinSet();
 32         void Init();
 33         void Union(int x,int y);
 34         int Find(int x);
 35         bool itsSame(int x,int y);
 36 };
 37 
 38 DisJoinSet ::DisJoinSet(int n)
 39 {
 40     this->n = n;
 41     tree = new node[n+1];
 42     Init();
 43 }
 44 
 45 DisJoinSet ::~DisJoinSet()
 46 {
 47     delete []tree;
 48 }
 49 
 50 void DisJoinSet::Init()
 51 {
 52     for(int i = 1; i <= n; i ++)
 53     {
 54         tree[i].no = i;
 55         tree[i].rank = 0;
 56         tree[i].parent = i;
 57         tree[i].relation = 0;
 58     }
 59 }
 60 
 61 int DisJoinSet ::Find(int x)
 62 {
 63     int temp = tree[x].parent;//temp x的父親結點
 64     if(x != tree[x].parent)
 65     {
 66         tree[x].parent = Find(tree[x].parent);//遞歸在雙親中找x
 67     // tree[temp].relation必爲temp結點(x的父節點)與根節點的關係,tree[x].relation最初爲x與temp的關係,
 68     // tree[x].relation == tree[temp].relation意味着tree[x].relation和tree[temp].relation同爲1,或者同爲0
 69     // 若是tree[x].relation和tree[temp].relation同爲1,意味着根節點與temp不一樣類,temp與x不一樣類,總共只有2個集合,x與根節點一定同類。
 70     // 若是tree[x].relation和tree[temp].relation同爲0,意味着根節點與temp同類,temp與x同類,x與根節點也一定同類。
 71         if(tree[x].relation == tree[temp].relation)
 72         {
 73             tree[x].relation = 0;
 74         }
 75     // tree[x].relation != tree[temp].relation意味着tree[x].relation和tree[temp].relation一個爲1,一個爲0,
 76     // 若是tree[temp].relation爲false,tree[temp].relation爲1,意味着根節點和temp同類,temp與x不一樣類,那麼x與根節點必然不一樣類
 77     // 若是tree[temp].relation爲true,tree[x].relation爲0,意味着根節點和temp不一樣類,temp與x同類,那麼x與根節點必然不一樣類
 78         else
 79         {
 80             tree[x].relation = 1;
 81         }    
 82         return tree[x].parent;// 返回根節點下標
 83     }
 84     else
 85     {
 86         return x;
 87     }
 88 }
 89 
 90 void DisJoinSet ::Union(int x,int y)
 91 {
 92     int rootx = Find(x);
 93     int rooty = Find(y);
 94     if(rootx == rooty)
 95     {
 96         return ;
 97     }
 98     if(tree[rootx].rank > tree[rooty].rank)
 99     {
100         tree[rooty].parent = rootx;
101         // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty
102         // 若是tree[x].relation和tree[y].relation均爲1,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類;
103         // 若是tree[x].relation和tree[y].relation均爲0,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類
104         if(tree[x].relation == tree[y].relation)
105         {
106             tree[rooty].relation = 1;
107         }
108         // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類;
109         // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類;
110         else
111         {
112             tree[rooty].relation = 0;
113         }
114     }
115     else
116     {
117         tree[rootx].parent = rooty;
118         if(tree[rootx].rank == tree[rooty].rank)
119         {
120             tree[rooty].rank ++;
121         }
122         // 此時rooty與其根結點rootx的關係如何肯定?由於Find方法也在進行路徑壓縮,x的父節點是rootx,y的父節點的rooty
123         // 若是relation[x]和relation[y]均爲true,說明x和rootx不一樣類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx不一樣類;
124         // 若是relation[x]和relation[y]均爲false,說明x和rootx同類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx不一樣類
125         if(tree[x].relation == tree[y].relation)
126         {
127             tree[rootx].relation = 1;
128         }
129         // 若是tree[x].relation爲1,tree[y].relation爲0,說明x和rootx不一樣類,y和rooty同類,而已知x和y不一樣類,所以rooty和rootx必同類;
130         // 若是tree[x].relation爲0,tree[y].relation爲1,說明x和rootx同類,y和rooty不一樣類,而已知x和y不一樣類,所以rooty和rootx必同類;
131         else
132         {
133             tree[rootx].relation = 0;
134         }
135     }
136 }
137 
138 
139 bool DisJoinSet::itsSame(int x,int y)
140 {
141     return (tree[x].relation == tree[y].relation);
142 }
143 
144 
145 int main()
146 {
147     int T;
148     while(scanf("%d",&T) !=EOF )// 沒有EOF 會 OLE
149     {
150         if(T == 0)break;
151         for(int i = 0; i < T; i++)
152         {
153             int N;
154             int M;
155             scanf("%d%d",&N,&M);
156             DisJoinSet dis(N);
157             char s1[2];
158             int s2,s3;
159             for(int i= 0; i < M ;i ++)
160             {
161                 scanf("%s%d%d",s1,&s2,&s3);
162                 int pa = dis.Find(s2);
163                 int pb = dis.Find(s3);
164                 if(s1[0] == 'A')
165                 {
166                     if(pa != pb)
167                     {
168                         cout<<"Not sure yet."<<endl;
169                     }
170                     else if(dis.itsSame(s2,s3) )
171                     {
172                         cout<<"In the same gang."<<endl;
173                     }
174                     else//根相同 可是rela不一樣,說明再也不統一gangs
175                     {
176                         cout<<"In different gangs."<<endl;
177                     }
178                 }
179                 if(s1[0]=='D')
180                 {
181                     if(pa != pb)
182                     {
183                         dis.Union(s2,s3);
184                     }
185                     
186                 }
187             }
188         }
189     }
190     return 0;
191 }
View Code
相關文章
相關標籤/搜索