并查集(以hdu1232 畅通工程为例)

来源:互联网 发布:sql 列出表中所有字段 编辑:程序博客网 时间:2024/06/03 14:56

这也算是我学的第一个比较牛逼的算法了吧,寒假集训的时候看了一中午,结果还是只会做这种最简单。。怎么说 任重而道远啊 ,现在开始上题 

题目就是 很简单的,超级简单的并查集,所谓并查集就是在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

下面直接上代码:


#include<stdio.h>int p[1000];//定义全局变量,以后的归并要用int getf(int v)//找到祖先的函数{    return v==p[v]?v:p[v]=getf(p[v]);//这个函数的意思就是,如果这个数字就是“祖先”的话,我们就返回这个祖先,如果不是得话,那就递归调用,直到这个是数他的祖先为止}void merge(int u,int v){    int x=getf(u);//对于传递的两个参数,开始找到祖先    int y=getf(v);    if(x!=y)//如果这两个的祖先不一样,就开始并在一起    {        p[y]=x;//这里按照《《啊哈算法》》的描述就是靠左原则    }}int main()//根据题意构建主函数{    int n,m,i;//n表示城市的序号,m表示路的条数    int a,b;//a,b分别是各种路的编号    while(scanf("%d",&n)!=EOF)    {        int sum=0;        if(n==0)        {            break;        }        scanf("%d",&m);        for(i=1;i<=n;i++)//注意这里,这里编号是有等于号的        {            p[i]=i;//初始化并查集        }        for(i=0;i<m;i++)        {            scanf("%d %d",&a,&b);            merge(a,b);        }        for(i=1;i<=n;i++)//这里也是,这里由于要看谁是最终的祖先所以要从1开始        {            if(p[i]==i)            {                sum++;            }        }        printf("%d\n",sum-1);//由于是修路,也就是 sum的值是有“几块儿”路,那么就需要这几块儿路链接,5块儿路就需要修4条路,也就是sum-1条路。    }    return 0;}


1 0
原创粉丝点击