并查集
我们来通过一个例题来学习这个有趣且不是很难得算法:
看看题目:
为什么是两个朋友圈呢?
1和2是朋友,然后2和3又是朋友,所以1,2,3三个人互为朋友关系,然后4和5是朋友,且4和5均与1,2,3没有关系,所以就有两个朋友圈,分别是1,2,3和4,5;
好,现在题目理解了,怎么用代码来解决这个问题呢?
这里我们就要用到并查集了;
并查集
通过一个一维数组来实现,就好比这题来讲,一开始,每个人都是只有自己一个人的,后来慢慢互相交朋友,在每次判断两个人是否构成一个朋友圈时,还要注意找到他们得共同朋友。
话不多说,看代码:
#include<stdio.h>
int h[100000]={0};
int find(int p)//通过这个递归函数来找到自己所属的那个朋友圈,也就是找到此朋友圈里最早的一个朋友
{
if(h[p]==p)
return p;
else//这里是路径压缩,函数返回的时候,把我的新朋友改为最后找到的最早的朋友的编号
{
h[p]=find(h[p]);//这里进行了路径压缩
return h[p];
}
}
void father(int x,int y)//这是合并两个朋友的函数
{
int x1,y1;//x1,y1分别为x和y的朋友
x1=find(x);
y1=find(y);
if(x1!=y1)//判断他们是否属于同一个朋友圈
h[y1]=x1;
return;
}
int main()//代码从主函数开始看比较容易理解
{
int n,m;
scanf("%d%d",&n,&m);
int sum=0;
for(int i=1;i<=n;i++)
h[i]=i;//初始化数组,数组里面存自己的下标,表示一开始只有自己,没有朋友
int a,b;
for(int j=1;j<=m;j++)
{
scanf("%d%d",&a,&b);
father(a,b);//开始找到自己的朋友圈
}
for(int k=1;k<=n;k++)//最后遍历,找出有多少个朋友圈
{
if(h[k]==k)
sum++;
}
printf("%d",sum);
}
以上就是我对并查集的理解。