并查集

背景

并查集:顾名思义就是“合并集合”和“查找集合中的元素”两种操作合二为一的算法。考研中可以应用于克鲁斯卡尔算法中。
1,初始化
可以用数组实现并查集,定义并查集数组为:parent[ ]
对于每一个元素 parent[x]指向x在树形结构上的父亲节点。如果x是根节点,则令parent[x] = x。

2,查找
对于查找操作,假设需要确定x所在的的集合,也就是确定集合的代表元。可以沿着parent[x]不断在树形结构中向上移动,直到到达根节点。下面为代码:

int getRoot(int a)
{
	while(a!=parent[a])
		a=parent[a];
	return a;

3,合并
对于两个集合,只需找到其中一个的根,使其成为另一集合中任意节点的孩子即可。

a=getRoot(a)
if(a!=b)
	parent[a]=b;

在这里插入图片描述

4,判断两个节点是否在同一集合
找到两个节点的根,相同就是同一集合,不同就不是。

Kruskal算法

一开始并查集所有节点都各自独立,根节点为本身。
对图的边按权值从小到大排序。
循环从小到大读取每个边的两个节点a,b
获取a、b的根节点
如果a、b不属于同一集合,执行合并(第一次是将一条边记录在一个集合中;后面不断将新边融入集合,并且避免相同集合的边重复合并。)
如:已有0->2->1;那么0->1就不会被合并到该集合。
直到所有的边被检测完成。

typedef struct
{
	int a,b;
	int w;
}Road;//记录图的边,节点以及权重
Road road[Maxisize];
int v[Maxsize];//并查集数组

//利用并查集找节点的根
int getRoot(int a)
{
	while(a!=v[a])
		a=v[a];
	return a;
}

void Kruskal(MGraph g,int &sum,Road road[])
{
	int i,N,E,a,b;
	N=g.n;
	E=g.e;
	sum=0;
	for(i=0;i<N;++i)//初始并查集,各种为类
		v[i]=i;
	sort(road,E);//对边按从小到大排序
	for(i=0;i<E;++i)
	{
		//边左右端点的根
		a=getRoot(road[i].a);
		b=getRoot(road[i].b);
		//不属于同一集合
		if(a!=b)
		{
			//合并,记录权重
			v[a]=b;
			sum+=road[i].w;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕南路GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值