有关并查集,最关键的就是两个函数,一个是find(查找),一个是merge(合并),有关并查集的两个函数,也有两种书写的方法,两种书写方法的复杂度是不同的,一种是查找快,合并慢,一种是查找慢,合并快。小编给出的模板则是第二种,因为第二种的使用更加普及,这种并查集的话虽然查找慢,但是我们可以对其进行路径压缩,路径压缩也是比较好理解的,就是说如果让所有点都指向根节点的话,那么查找的复杂度就会变的比之前低,特别是在需要大量查询的时候。在写法上,我们可以采用递归,当然无论是做题还是工作,我们都是不推荐用递归的,这里小编也是给出的是非递归的写法。
#include <stdio.h>//简易并查集
int set[1002];
int find(int x)
{
int k, j, r;
r = x;
while(r != set[r]) //查找跟节点
r = se[r]; //找到跟节点,用r记录下
k = x;
while(k != r) //非递归路径压缩操作
{
j = set[k]; //用j暂存parent[k]的父节点
set[k] = r; //parent[x]指向跟节点
k = j; //k移到父节点
}
return r; //返回根节点的值
}
void merge(int x,int y)
{
int a,b;
a=find(set[x]);
b=find(set[y]);
if(a!=b)
set[a]=set[b];
}
int main()
{
int n,m,i,x1,x2,count;
while(scanf("%d",&n)&&(n!=0))
{
scanf("%d",&m);
for(i=1;i<=n;i++)
set[i]=i;
while(m--)
{
scanf("%d%d",&x1,&x2);
merge(x1,x2);
}
for(count=-1,i=1;i<=n;i++)
if(set[i]==i)
count++;
printf("%d\n",count);
}
return 0;
}