关于并查集
并查集就是将有关系的一些元素放在一个集合里
为他们搭建某种关系
能通过其中一个元素便得到与他有关的其他元素
如何搭建关系
要实现可追溯性,我们可以利用数组下标
规定一个root(头元素),root[root]=root
而与其有关的下一个元素比如a,root[a]=root。
以此类推root[b]=a。
路径优化
当有关系的元素很多的时候,我们关联至最后一个元素时已经递推了很多层了,为了下一次用的时候不再浪费时间,我们将他直接连至头元素上,即改变他的上层。
while(i!=root)//进行路径优化
{
j=per[i];//保存上一层
per[i]=root;
i=j;//当前层赋为上一层
}
具体应用
数数有几个朋友圈:
有n个人,编号1-n。
现在有一个舞会,在舞会上,大家会相互介绍自己的朋友。
即: 如果a认识b,b认识c。那么在舞会上,a就会通过b认识到c。
现在,给出m个关系
每个关系描述:
a b
表示 编号为a和编号为b的人是朋友关系。
代码实现:
#include<stdio.h>
int per[202020];
int findfriend(int x)
{
int root=x;
while (root!=per[root])
root=per[root];
int i=x,j;
while(i!=root)//进行路径优化
{
j=per[i];//保存上一层
per[i]=root;
i=j;//当前层赋为上一层
}
return root;
}
int main()
{
int n,m,i,a,b,r,t;
while(~scanf("%d%d",&n,&m))
{
for(i=1; i<=n; i++)
per[i]=i;
while(m--)
{
scanf("%d%d",&a,&b);
r=findfriend(a);
t=findfriend(b);
if(r!=t)
{
per[r]=t;
}
}
int ans=0;
for(i=1; i<=n; i++)
if(per[i]==i)
ans++;
printf("%d\n",ans);
}
return 0;
}