并查集原理,模板及优化

什么是并查集

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题,可以用来检查一个图中是否存在一个环。

算法原理

在这里插入图片描述在这里插入图片描述

代码模板

#include<iostream>
using namespace std;
int parent[1010];	
int n,m;
void  init(int n)//初始化
{
	for(int i=1;i<=n;i++)
	{
		parent[i]=-1;
	}
}
int find_root(int x,int parent[])//查找根节点
{
	int x_root=x;
	while(parent[x_root]!=-1)//只有根节点才是-1
	{
		x_root=parent[x_root];
	}
	return x_root;
}
int unite(int x,int y,int parent[])//链接,返回0说明不用连接(即在一棵树上)
//返回1表示可以连接
{
	int x_root=find_root(x,parent);
	int y_root=find_root(y,parent);
	if(x_root==y_root)
	{
		return 0;
	}
	else
	{
		parent[x_root]=y_root;
		return 1;
	}
}

并查集的优化

在这里插入图片描述

优化代码模板

#include<iostream>
using namespace std;
int parent[1010];	
int n,m;
void  init(int n,int rank[])
{
	for(int i=1;i<=n;i++)
	{
		parent[i]=-1;
		rank[i]=0;
	}
}
int find_root(int x,int parent[])
{
	int x_root=x;
	while(parent[x_root]!=-1)
	{
		x_root=parent[x_root];
	}
	return x_root;
}
int unite(int x,int y,int parent[],int rank[])
{
	int x_root=find_root(x,parent);
	int y_root=find_root(y,parent);
	if(x_root==y_root)
	{
		return 0;
	}
	else
	{
		//parent[x_root]=y_root;
		if(rank[x_root]>rank[y_rank])
		parent[y_root]=x_root;
		else if(rank[x_root]<rank[y_root])
		parent[x_root]=y_root;
		else//两棵树高度相等任选一棵连接到另一棵上,同时另一棵的高度加一
		{
			parent[x_root]=y_root;
			rank[y_root]++;
		}
		return 1;
	}
}

题目练习
在这里插入图片描述在这里插入图片描述
代码:

#include<iostream>
using namespace std;
int parent[1010];	
int n,m;
void  init(int n)
{
	for(int i=1;i<=n;i++)
	{
		parent[i]=-1;
	}
}
int find_root(int x,int parent[])
{
	int x_root=x;
	while(parent[x_root]!=-1)
	{
		x_root=parent[x_root];
	}
	return x_root;
}
int unite(int x,int y,int parent[])
{
	int x_root=find_root(x,parent);
	int y_root=find_root(y,parent);
	if(x_root==y_root)
	{
		return 0;
	}
	else
	{
		parent[x_root]=y_root;
		return 1;
	}
}
int main ( )
{
	while(cin>>n&&n)
	{
		cin>>m;
//		int parent[n+1];
		init(n);
		int x,y;
		for(int i=1;i<=m;i++)
		{
			cin>>x>>y;
			unite(x,y,parent);	
		}	
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			if(parent[i]==-1)//看形成了几棵树,最后将它们连接就可
			{
				ans++;
			}
		}
		cout<<ans-1<<endl;
	}	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值