首页 > 编程语言 >详解 Kruskal 最小生成树算法

详解 Kruskal 最小生成树算法

时间:2023-01-09 14:56:49浏览次数:57  
标签:return int Kruskal 查集 fa 算法 详解 find

 求最小生成树算一般有两种算法: PrimKruskal 。 Prim 的时间复杂度为 \(O(|V|^{2})\) ,更适合稠密图。而 Kruskal 的时间复杂度为 \(O(logV)\) 或 \(O(logE)\) 。更适合稀疏图,下面就讲一下 Kruskal 算法的实现。

1.并查集

  Kruskal 的核心就是并查集,并查集在 Kruskal 中的作用为 判断两个点是否已经联通

1.并查集的初始化

 并查集是用一个数组储存的,数组下标代表点的序号,而数组下标对应的内容则代表这个点的父亲。在最开始每个点都是独立的,因此每个点的父亲都是自己。

初始化代码:

fa[1005];
...
for(int i = 1;i <= n;i++)
{
fa[i] = i;
}
2.并查集的查找

 并查集的查找找的是这个点的最远祖先,代码为:

int find(int x){
    if(p[x]==x)
        return x;
    else
        return find(p[x]);
}

但是这种方法效率较慢,下面是一种路径压缩的查找方式。

int find(int x)
{
    if(par[x]==x)
        return x;

        fa[x]=find(fa[x]);   
        return par[x];
}

也可以写为:

int find(int x)
{
    return fa[x]=x?x:fa[x]=find(fa[x]);
}

此时 find(x) 的返回值即为这个点的最远祖先。

3.并查集合并

 并查集的名字中有“并”和"查”字,所以并查集的核心就在于合并查找
例如,下图为并查集的初始状态。

蝠气满满

将 1 和 3合并后的状态:

蝠气满满

使用树表示为:

蝠气满满

并查集合并的代码为:

void merge(int i,int j){
    fa[find(j)] = find(i);
}

2.Kruskal算法

Kruskal 的思想为对每条边的长度进行排序,从短到长一次取边,当这条边所连的点未连接时,将两点进行合并。

图解

例如要求下面这个图的最小生成树的权值。
蝠气满满

1.对所有边的长短进行排序:

1 2 3 4 5 6
1 0 4 0 5 0 0
2 4 0 3 0 0 0
3 0 3 0 2 6 1
4 5 0 2 0 9 0
5 0 0 6 9 0 10
6 0 0 1 0 10 0

2.从短到长依次取边,当使用并查集判断两点未连接时,进行合并。
3.最后得到最小生成树如图,权值和为 16 。

蝠气满满

例题:拆地毯

代码为:

#include<bits/stdc++.h>
using namespace std;
int find(int x);
int f[100003];
struct edge
{
	int u;
	int v;
	int dis;
}ed[100000];
bool cmp(edge a,edge b)
{
	return a.dis>b.dis;
}
int Kruskal(int m,int k)
{
	int ans=0;int num = 0;
	for(int i = 1;i<=m;i++)
	{
		int fu=find(ed[i].u);
		int fv=find(ed[i].v);
		if(fu==fv) continue;
		if(fu!=fv)
		{
		f[fu]=fv;
		ans+=ed[i].dis;
		num++;
		if(num==k) break;	
		} 
	}
	return ans;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 1;i<=n;i++)	f[i]=i;
	
	for(int i = 1;i<=m;i++)
	{
		int x,y,d;
		scanf("%d%d%d",&x,&y,&d);
		ed[i].u=x; ed[i].v=y; ed[i].dis=d;
	}
	sort(ed+1,ed+1+m,cmp);
	printf("%d",Kruskal(m,k));
	return 0;
} 

标签:return,int,Kruskal,查集,fa,算法,详解,find
From: https://www.cnblogs.com/demc/p/17037009.html

相关文章

  • ACM&OI 多项式算法专题
    ACM&OI基础数学算法专题一、FFT基础拉格朗日插值复数的运算性质和几何性质单位根和单位根反演快速傅里叶变换(FFT)的分治实现快速傅里叶逆变换(IFFT)快速傅里叶变换的......
  • rwctf体验赛-Snake详解
    首先展示一下apk中的内容,一个简单的贪吃蛇游戏静态分析蛇撞墙会有提示,直接去看定位到com.example.ct_sanke.SnakeView.i()i()方法只有一处调用,随着蛇吃食物进行逻......
  • 退火算法学习笔记
    初创建于2022-02-0900:29前段时间学习了一下退火算法。这里简单记一下踩过的坑~退火算法是一种搜索算法,我认为其核心思想便是”以一定的概率接受一个更差的解“,这样可......
  • 【车间调度】基于GA/PSO/SA/ACO/TS优化算法的车间调度比较(Matlab代码实现)
    目录1概述2 FJSP描述3运行结果3.1main1运行结果3.2main2运行结果4Matlab代码 5参考文献6写在最后1概述柔性作业车间调度问题(FlexibleJobshopSched-ulingPro......
  • 深度强化学习专栏 —— 2.手撕DQN算法实现CartPole控制
    我将文章发表在了古月居,一起来看看吧!​​戳这里​​......
  • Windows中的SID详解
    SID详解前言SID也就是安全标识符(SecurityIdentifiers),是标识用户、组和计算机帐户的唯一的号码。在第一次创建该帐户时,将给网络上的每一个帐户发布一个唯一的SID。Windo......
  • 【linux】RabbitMQ学习-vhost 详解
    vhost本质上是一个mini版的RabbitMQ服务器,拥有自己的队列、绑定、交换器和权限控制;vhost通过在各个实例间提供逻辑上分离,允许你为不同应用程序安全保密地运行数据;vhost是......
  • 关于快速排序算法最多比较次数与最少比较次数的问题
    关于快速排序算法最多比较次数与最少比较次数的问题最常见的快速排序算法的衡量标准是时间复杂度,即最坏情况\(O(n)\),最优与平均情况均为\(O(n\log_2^n)\)。最近看到......
  • 一文详解|影响成长的关键思考
    序:之前看过杨振宁的一个采访,说他最大的成就,不是获得了诺贝尔奖的研究,而是之前的一个普通理论的研究:他坚信事物是遵循一定规律的,不是大家认为的不可捉摸,花了7年时间,陆陆续......
  • nacos详解二
    SpringBoot集成Nacos启动配置管理1.添加依赖      <dependency>  <groupId>com.alibaba.boot</groupId>  <artifactId>nacos-config-sp......