并查集
我们结合一个题目来彻底了解这个算法吧。
问题 A: 朋友圈
有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
我们把这个题目当成社会,不是朋友我们肯定就要打架,打完架就是朋友了。那是朋友我们肯定不要打架吧,那a和b是不是朋友??
这我怎么知道。。
所以大家就弄了个朋友圈,挑一个人做老大,老大一样我们自然是朋友
好,那我们老大不一样怎么办,我们不是朋友呗,打一架,怎么打呢??那就要老大出马,打赢了你们归我们老大管,输了我们归你们老大管,好,结束。
出代码:
#include<stdio.h>
int a[500000];
int find(int zz)
{
int x;
int y;
x=zz;
while(zz!=a[zz])//找老大
{
zz=a[zz];//我只认识我的上级
}
while(x!=zz)//这里zz为老大
{
y=a[x];
a[x]=zz;
x=y;
}//(只是一个交换代码,不要想太多,)把所有下级归老大管,方便别人查找老大
return zz;//把老大告诉他
}
main()
{
int n,m,s,k,i,l,kboss,lboss;
while(~scanf("%d%d",&n,&m))
{
s=n;
for(i=1; i<=n; i++)
{
a[i]=i;
}
while(m--)
{
scanf("%d%d",&k,&l);
if(k>=1&&k<=n&&l>=1&&l<=n)
{
kboss=find(k);//他去找自己的老大
lboss=find(l);//他也去找自己的老大
if(kboss!=lboss)//两个老大不一样,就是打,输了的归对手管。
{
a[kboss]=lboss;//老大归我管了,其他人也只能服从我。
s--;//以后都是朋友,同处一个朋友圈,敌人减一;
}
}
}
printf("%d\n",s);//输出最终朋友圈
}
}
当今社会,不服就是干。