并查集

可紊 提交于 2020-01-23 22:16:27

并查集就是最开始又N个集合,这N个集合当中有一部分集合存在关联,就可以把有关联的集合合并在一起,这个关联也可以间接建立,所以要查找是否间接存在关联,最后得出剩余的集合数。

题目描述
有n个人,编号1-n。
现在有一个舞会,在舞会上,大家会相互介绍自己的朋友。
即: 如果a认识b,b认识c。那么在舞会上,a就会通过b认识到c。
现在,给出m个关系
每个关系描述:
a b
表示 编号为a和编号为b的人是朋友关系。

输入格式
输入n和m
接下来m行,每行为a b
输出格式
最后问,会有多少个朋友圈。

样例输入
5 3
1 2
2 3
4 5
样例输出
2

步骤:

初始化
先建立一个数组,用数组下标表示集合。

void fun(int n)
{
    for(int i=1; i<=n; i++)
        p[i]=i;
}

查找
因为每个集合最开始的值就是下标,代表还没有合并。当输入1 2时,说明1和2集合要合并为同一个集合。方法就是把p[1]的值由1变成2,也就是现在1和2就同属于一个集合里面。随后输入2 3。同理把p[2]的值变成3。集合又减少一个。
这一步通过find函数来实现。

b1=find(p1);
b2=find(p2);
if(b1!=b2)
{
   p[b1]=b2;
}
int find(int x)
{
while(x!=p[x])
    {
        x=p[x];
    }
 return(x);
 }

路径压缩
如果在输入了1 2,2 3,在输入1 3,也就是都通过2间接认识的时候,时会导致查找的时候变得很乱很复杂,解决的办法就是,路径压缩,把所有同属于一个集合的值变成同一个值。这一步直接加在find函数里面。

int find(int x)
{
    int temp,n=x;
    while(x!=p[x])
    {
        x=p[x];
    }
    while(n!=x)//路径压缩
    {
        temp=p[n];
        p[n]=x;
        n=temp;
    }
    return(x);
}

得出结果
根据上面的步骤可以看出,想求合并后剩余的集合只要判断数组值与下标是否相等就可以了。如果相等说明没有被合并。

int ans=0;
for(i=1;i<=n;i++)
if(p[i]==i)
ans++;
printf("%d\n",ans);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!