HDU-1232-畅通工程
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1232
/*
程序分析:
给你一些城市、城市之间的某些路,让你求最少还要再建多少条路才能实现城市与城市之间两两相通。
需要注意的是,两个城市之间可以有多条路,多条也当它一条处理。如果城市之间都没有路,需要建的路
就是城市的个数减一。
解决方法:
利用并查集的特性,把城市之间有路的合并为一个城市,最后判定有几个城市或者有几棵树就可以了。
结果也就是城市(树)数目减一,比如有三个城市就要有2条路来让他们互通! 具体看代码吧
*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 using namespace std; 3 const int Max = 1000+10; 4 int far[Max]; 5 int sign[Max]; 6 int rank[Max]; 7 int map[Max][Max]; 8 9 void make_set(int n) 10 { 11 for(int i=0; i<=n; i++) 12 { 13 far[i] = i; 14 rank[i] = 0; 15 } 16 } 17 18 int find_2(int x) 19 { 20 int i=0; 21 while(far[x] != x) 22 { 23 sign[i++] = x; 24 x = far[x]; 25 } 26 while(i--) 27 { 28 far[sign[i]] = x; 29 } 30 return x; 31 } 32 33 34 int find(int x) 35 { 36 if(far[x] != x) 37 return far[x] = find(far[x]); 38 return far[x]; 39 } 40 41 void uni(int a, int b) 42 { 43 a = find(a); 44 b = find(b); 45 if(a == b) 46 return; 47 if(rank[a] < rank[b]) 48 far[a] = b; 49 else if(rank[a] > rank[b]) 50 far[b] = a; 51 else 52 { 53 far[a] = b; 54 rank[b]++; 55 } 56 } 57 58 int main() 59 { 60 int n, m; 61 int a, b; 62 while(cin>>n>>m && n) 63 { 64 make_set(n); //初始化 65 66 if(m==0) 67 { 68 cout<<n-1<<endl; 69 continue; 70 } 71 for(int i=0; i<m; i++) 72 { 73 scanf("%d%d", &a, &b); 74 uni(a, b); 75 } 76 int ans=0; 77 for(int j=1; j<=n; j++) 78 { 79 if(find(j) == j) 80 ans ++; 81 } 82 cout<<ans-1<<endl; 83 } 84 85 return 0; 86 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 using namespace std; 3 #define max 50001 4 5 int p[max]; 6 bool k[max]; 7 8 int find(int pos) 9 { 10 if(p[pos]==-1)return pos; 11 return p[pos]=find(p[pos]); 12 } 13 int uni(int x,int y) 14 { 15 int a=find(x); 16 int b=find(y); 17 if(a==b)return 0; 18 p[a]=b; 19 return 1; 20 } 21 22 int main() 23 { 24 int temp; 25 int a,b; 26 int n,m; 27 while(cin>>n&&n&&cin>>m) 28 { 29 //初始化 30 for(int i=1;i<=n;i++) 31 { 32 p[i]=-1; 33 k[i]=0; 34 } 35 //输入 合并 36 for(int i=1;i<=m;i++) 37 { 38 cin>>a>>b; 39 uni(a,b); 40 } 41 //标记 42 for(int i=1;i<=n;i++) 43 { 44 temp=find(i); 45 k[temp]=1; 46 } 47 //统计 48 int add=0; 49 for(int i=1;i<=n;i++) 50 { 51 if(k[i]==1) 52 add++; 53 } 54 printf("%d\n",add-1); 55 } 56 return 0; 57 }