幷查集拓展
拓展就是說並不是很明顯的可以套幷查集的模板,或者是要拐個彎的,或者幷查集優化的之類...
poj 1703.Find them, Catch them
這題就是兩個團伙,輸入A代表判斷這兩個人是否一個團伙,不同團伙,或者不確定;而輸入D則表示兩個人不是一個團伙;
如果用幷查集的話,我們一般是合併同一個團伙的,但是我一開始想的是反其道而行,合併不同團伙的,這是可以的,然後再
用0和1標記一下是否是一個團伙,但是想的很亂,搞了好久沒做出來,結果...發現了一種很神奇的方法,佩服佩服:
因為是兩個團伙,所以我們把數組擴展一下,比如四個人1,2,3,4,我們把編號擴展成1,2,3,4,5,6,7,8;當輸入1,2不是同一個團伙,
我們就是1+4=5和2作為一個團伙(5,2),1和2+4=6作為一個團伙(1,6);當再輸入2,3不是一個團伙,那麼(2,7), (6,3),這樣我們
就找到了(1,6)和(6,3)可以合併到一起,表示(1,3)是一伙的!太巧妙了,怎麼想得到!
1 // poj 1703.Find them, Catch them 2 // 并查集 高级 3 // references: 4 // http://www.hankcs.com/program/cpp/poj-1703-find-them-catch-them.html 太巧妙了 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 #include <algorithm> 9 10 using namespace std; 11 12 const int N = 200105; 13 14 int p[N]; 15 int n, m; 16 17 void init() 18 { 19 for(int i=0; i<N; i++) 20 { 21 p[i] = -1; 22 } 23 } 24 25 int find(int x) 26 { 27 return p[x] == -1 ? x : p[x] = find(p[x]); 28 } 29 30 void union_set(int u, int v) 31 { 32 int x = find(u); 33 int y = find(v); 34 if(x != y) 35 { 36 p[x] = y; 37 } 38 } 39 40 int main() 41 { 42 int t; 43 scanf("%d", &t); 44 while(t--) 45 { 46 init(); 47 scanf("%d%d", &n, &m); 48 for(int i=0; i<m; i++) 49 { 50 getchar(); 51 int u, v; 52 char s; 53 scanf("%c%d%d", &s, &u, &v); 54 if(s == 'A') 55 { 56 if(find(u) == find(v)) 57 { 58 printf("In the same gang.\n"); 59 } 60 else if(find(u) == find(v + n) || find(u + n) == find(v)) 61 { 62 printf("In different gangs.\n"); 63 } 64 else 65 printf("Not sure yet.\n"); 66 } 67 else 68 { 69 union_set(u, v + n); 70 union_set(u + n, v); 71 } 72 } 73 } 74 return 0; 75 }
最後要注意scanf的緩衝區的問題啊啊啊...輸入%c的時候,注意回車要getchar()掉!!!