畅通工程 - 并查集的应用
嘿 , 狗日的没想到一次就过了 , 看来数据挺水![](https://images2015.cnblogs.com/blog/829161/201605/829161-20160526181018116-125476050.png)
![](https://images2015.cnblogs.com/blog/829161/201605/829161-20160526181023663-1124954583.png)
并查集的简单应用 . 直接 上 代码了.
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<set> 9 #include<stack> 10 #include<string> 11 #include<sstream> 12 #include<map> 13 #include<cctype> 14 #include<limits.h> 15 using namespace std; 16 #define len 1005 17 int father[len],sum; 18 int Find(int x) // 做了时间上的优化 ,但是 在空间复杂度上比较高 19 { 20 if(x!=father[x]) 21 father[x]=Find(father[x]); 22 sum++; 23 return father[x]; 24 } 25 bool Merge(int x,int y) // 做了时间复杂度上的优化 让并查集的 深度尽量 浅 26 { 27 int sum1,sum2; 28 sum=0; 29 x=Find(x); 30 sum1=sum; // x 的深度 31 sum=0; 32 y=Find(y); 33 sum2=sum; // y 的深度 34 if(x!=y) 35 { 36 if(sum1>sum2) 37 father[y]=x; 38 else 39 father[x]=y; 40 return true; 41 } 42 else 43 return false; 44 } 45 struct road 46 { 47 int x,y; 48 }a[len]; 49 int main() 50 { 51 int n,m; 52 while(scanf("%d%d",&n,&m)) 53 { 54 if(n==0) 55 break; 56 for(int i=0;i<=n;i++) 57 father[i]=i; 58 for(int i=0;i<m;i++) 59 { 60 int q,w; 61 scanf("%d%d",&q,&w); 62 Merge(q,w); 63 } 64 int mark=0; 65 for(int i=1;i<=n;i++) 66 { 67 father[i]=Find(i); 68 } 69 for(int i=1;i<=n;i++) 70 { 71 if(father[i]==i) 72 mark++; 73 } 74 printf("%d\n",mark-1); 75 } 76 }