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;}


原创粉丝点击