Find them, Catch them(并查集)
http://poj.org/problem?id=1703
题意:有两个黑帮团伙,共n名团伙成员(不知道属于这两个黑帮中的哪一个)。现在警察有一些信息,每条信息包含2个人的编号,如果给出A a b,则输出a b的关系,即是否属于同一个黑帮;
如果给出D a b,则说明a b属于不同的黑帮。
思路:典型的并查集,只要两者的关系确定了,就将他们放入同一个集合内,而另外增加一个表示关系的数组link[]来表示该节点与其父亲的关系,0表示同一类,1表示不同团伙。初始时集合只有自己一个元素,link[] 初始为0。
第一次用c++的输入输出,TLE了。。改成C的就A了。
TLE 代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 const int N=100005; 5 int f[N],link[N]; 6 int n,m; 7 8 int find(int x) 9 { 10 int t = f[x]; 11 if (x!=f[x]) 12 f[x] = find(f[x]); 13 link[x] = (link[x]==link[t] ? 0 : 1); 14 return f[x]; 15 16 } 17 void merge(int x,int y,int fu,int fv) 18 { 19 f[fu] = fv; 20 link[fu] = (link[x]==link[y] ? 1 : 0); 21 } 22 void init() 23 { 24 for (int i = 0; i <= n; i ++) 25 { 26 f[i] = i; 27 link[i] = 0; 28 } 29 30 } 31 int main() 32 { 33 int T; 34 cin>>T; 35 while(T--) 36 { 37 38 cin>>n>>m; 39 init(); 40 while(m--) 41 { 42 int u,v; 43 char s; 44 cin>>s>>u>>v; 45 int fu = find(u); 46 int fv = find(v); 47 if (s=='A') 48 { 49 if(fu!=fv) 50 { 51 cout<<"Not sure yet."<<endl; 52 continue; 53 } 54 if (link[u]==link[v]) 55 { 56 cout<<"In the same gang."<<endl; 57 continue; 58 } 59 cout<<"In different gangs."<<endl; 60 continue; 61 } 62 if (s=='D') 63 { 64 if (fu!=fv) 65 merge(u,v,fu,fv); 66 } 67 68 } 69 } 70 return 0; 71 }
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 const int N=100005; 3 int f[N],link[N]; 4 int n,m; 5 6 int find(int x) 7 { 8 int t = f[x]; 9 if (x!=f[x]) 10 f[x] = find(f[x]); 11 link[x] = (link[x]==link[t] ? 0 : 1); 12 return f[x]; 13 14 } 15 void merge(int x,int y,int fu,int fv) 16 { 17 f[fu] = fv; 18 link[fu] = (link[x]==link[y] ? 1 : 0); 19 } 20 void init() 21 { 22 for (int i = 0; i <= n; i ++) 23 { 24 f[i] = i; 25 link[i] = 0; 26 } 27 28 } 29 int main() 30 { 31 int T; 32 scanf("%d",&T); 33 while(T--) 34 { 35 36 scanf("%d%d%*c",&n,&m); 37 init(); 38 while(m--) 39 { 40 int u,v; 41 char s; 42 scanf("%c%d%d%*c",&s,&u,&v); 43 int fu = find(u); 44 int fv = find(v); 45 if (s=='A') 46 { 47 if(fu!=fv) 48 { 49 printf("Not sure yet.\n"); 50 continue; 51 } 52 if (link[u]==link[v]) 53 { 54 printf("In the same gang.\n"); 55 continue; 56 } 57 printf("In different gangs.\n"); 58 continue; 59 } 60 if (s=='D') 61 { 62 if (fu!=fv) 63 merge(u,v,fu,fv); 64 } 65 66 } 67 } 68 return 0; 69 }