並查集能夠解決「是否暢通問題」,「是否有關係」這一類問題。c++
模板:spa
#include<bits/stdc++.h> using namespace std; int parent[10010]; //祖先,默認-1 void init(int n){ for(int i = 0;i<n;i++){ parent[i] = -1;//祖先的parent存該集合點數的負值 } } int find(int x){ /*尋找x的祖先的編號,若本身就是祖先,返回本身,順便作路徑壓縮 */ int s; for(s = x;parent[s]>=0;s = parent[s]);//找到了祖先 while(x!=s){ int tmp = parent[x]; parent[x] = s; x = tmp; } return s; } void Union(int a,int b){ int r1 = find(a),r2 = find(b); int total = parent[r1]+parent[r2]; if(parent[r1] > parent[r2]){ parent[r1] = r2; parent[r2] = total; } else{ parent[r2] = r1; parent[r1] = total; } } int main(){ int n,m,a,b; while(scanf("%d%d",&n,&m)){ //n條人 m條關係 init(n); for(int i = 0;i<n;i++){ scanf("%d%d",&a,&b); if(find(a)!=find(b)){ //不在同一集合中,則合併 Union(a,b); } } } return 0; }
題目:.net
HDU1272小希的迷宮 |
---|
上次Gardon的迷宮城堡小希玩了好久(見Problem B),如今她也想設計一個迷宮讓Gardon來走。可是她設計迷宮的思路不同,首先她認爲全部的通道都應該是雙向連通的,就是說若是有一個通道連通了房間A和B,那麼既能夠經過它從房間A走到房間B,也能夠經過它從房間B走到房間A,爲了提升難度,小希但願任意兩個房間有且僅有一條路徑能夠相通(除非走了回頭路)。小希如今把她的設計圖給你,讓你幫忙判斷她的設計圖是否符合她的設計思路。好比下面的例子,前兩個是符合條件的,可是最後一個卻有兩種方法從5到達8。 |
\(Input:\) 輸入包含多組數據,每組數據是一個以0 0結尾的整數對列表,表示了一條通道鏈接的兩個房間的編號。房間的編號至少爲1,且不超過100000。每兩組數據之間有一個空行。 整個文件以兩個-1結尾。 |
\(Output:\) 對於輸入的每一組數據,輸出僅包括一行。若是該迷宮符合小希的思路,那麼輸出"Yes",不然輸出"No"。 |
Sample Input設計
6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1
Sample Outputcode
Yes Yes No
/*使用並查集的解法*/ /*使用了一個set記錄頂點*/ #include<bits/stdc++.h> using namespace std; int parent[100010]; set<int> ditu; void init(int n){ for(int i = 0;i<n;i++){ parent[i] = -1; } ditu.clear(); } int find(int x){ int s; for(s = x;parent[s]>0;s = parent[s]); while(s!=x){ int tmp = parent[x]; parent[x] = s; x = tmp; } return s; } void Union(int a,int b){ int r1 = find(a),r2 = find(b); int tmp = parent[r1]+parent[r2]; if(parent[r1] > parent[r2]){ parent[r1] = r2; parent[r2] = tmp; }else{ parent[r2] = r1; parent[r1] = tmp; } } int main(){ int a,b; init(1001); int flag = 0; while(~scanf("%d%d",&a,&b)){ if(a!=0&&b!=0){ ditu.insert(a); ditu.insert(b); } if(a==-1 && b == -1) break; if(a==0&&b==0){ if(ditu.empty()) { printf("Yes\n"); } else if(flag == 1){ printf("No\n"); }else{ int cnt = 0; set<int>::iterator it; for(it = ditu.begin();it!=ditu.end();it++){ if(parent[*it] < 0) cnt++; } if(cnt==1) printf("Yes\n"); else printf("No\n"); } flag = 0; init(1001); continue; } if(find(a) != find(b)){ Union(a,b); }else{ flag = 1; } } }