并查集算法模板

并查集通过一个一维数组来实现,它的本质是维护一个森林,刚开始的时候,森林的每个点都是孤立的,也可以理解为每个点就是一棵只有一个节点的树,之后通过一些条件,逐渐将这些树合并成一棵大树。其实合并的过程就是“认爹”的过程。在“认爹”的过程中,要遵守“靠左”原则和“擒贼先擒王”的原则。在每次判断两个节点是否已经在同一棵树的时候(一棵树其实就是一个集合),也要注意必须求其根源,中间父亲节点是不能说明问题的,必须找到其祖宗(树的根节点),判断两个节点的祖宗是否是同一个根节点才行。并查集其实就是在“找祖宗”。

模板:

#include<stdio.h>
int f[10010],n,m;
void init()       //初始化 
{
	int i;
	for(i=1;i<=n;i++)
		f[i]=i;
	return;
}
//找爹的递归函数,不停地去找爹,直到找到祖宗为止 
int getf(int v)
{
	if(f[v]==v)
		return v;
	else
	{
		//这里是路径压缩,每次在函数返回的时候,顺带把路上遇到的人的“父亲 ”改为最后找到的祖宗的编号 
		f[v]=getf(f[v]);
		return f[v];
	}
}
void merge(int x,int y)
{
	int t1,t2;
	t1=getf(x);
	t2=getf(y);
	if(t1!=t2) //判断两个节点是否在同一个集合中,即是否是同一个祖先 
	{
		f[t2]=t1; //靠左原则 
	}
	return;
}
int main()
{
	int i,a,b,sum;
	scanf("%d%d",&n,&m);
	init();
	sum=0;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		merge(a,b);
	}
	for(i=1;i<=n;i++)
	{
		if(f[i]==i)
			sum++;
	}
	printf("%d\n",sum);
 } 

猜你喜欢

转载自blog.csdn.net/wan_ide/article/details/81478146
今日推荐