HDU ACM 1232.畅通工程(简单的并查集)
来源:互联网 发布:巨人网络信息披露 编辑:程序博客网 时间:2024/06/03 17:05
/**********************************题目大意:把是城镇之间道路的城镇有放到一组,n个城镇可以分成几组,并输出总组数-1(即只有当全部城镇在一个组时,才不需要再建道路);题目解析:运用并查集把有道路的城镇合并到一组,最后遍历数组father[i],查看i根结点是否为他自己;错误分析:1. 最主要的是题目已经知道总城镇数,应该把总城镇数运用参数传递给初始化的函数init() 2.这题与HDU 1213题相似,只需把输出结果变成rank1-1即可;*********************************/#include<cstdio>#include<iostream>using namespace std;#define M 1005int father[M],rank[M];//father[i]为i的父结点,rank[i]为i所属集合的总元素数void init(int n)//初始化,注意此时的函数init()有参数传递{ int i; for(i=1;i<=n;i++) { father[i]=i; // 各个元素独自构成一个集合 rank[i]=1; }}int find(int x)//查找根结点{ if(x!=father[x]) father[x]=find(father[x]); // 压缩路径,减少查询时运行的时间,使结点都指向根结点 return father[x];}void Union(int x,int y)// 合并{ x=find(x); //查找x的根结点 y=find(y); if(x!=y) //若两个x,y的根结点不同(即两个元素不再一个集合中),则合并两个集合 { father[x]=y; rank[y]+=rank[x]; }}int main(){ int n,m,i,x,y,t,rank1; while(scanf("%d",&n),n!=0) { scanf("%d",&m); init(n); rank1=0; while(m--) { scanf("%d %d",&x,&y); Union(x,y); } for(i=1;i<=n;i++) //遍历数组,找出有多少个子集合 { if(father[i]==i) rank1++; } printf("%d\n",rank1-1); } return 0;}