首页 > 其他分享 >从零开始学习Kruskal最小生成树

从零开始学习Kruskal最小生成树

时间:2023-03-08 21:22:26浏览次数:44  
标签:连通 int Kruskal 最小 生成 从零开始 权值

-1919810.前言

如果你想要学好Kruskal最小生成树的话,那么你就得先学好Kruskal最小生成树,你一看这个Kruskal最小生成树,你想掌握它还真不容易,基础知识里头你就得掌握Kruskal最小生成树、Kruskal最小生成树、甚至还有Kruskal最小生成树等高级算法!!所以这个Kruskal最小生成树的学习是层层递进的。

-114514.前置芝士

1.贪心

2.并查集

3.然后就没有啦

-1.正儿八紧的算法讲解

首先,既然它叫 Kruskal 最小生成树,那么它肯定是 Kruskal 发明的。

其次,最小生成树是什么你都不知道吧,那么就请看下面:


最小生成树

一个无向图的最小生成树就是在这张图中选出它的节点数 \(n\) - \(1\) 条边,使其能够通过这 \(n\) - \(1\) 条边构成一个连通图并且权值最小。

我们知道,一个无向图,如果只有它的节点数 \(n\) - \(1\) 条边,且连通,那么它就是一棵树,并且不能形成环。

所以它的名字叫做最小生成

注意,一个不连通的无向图没有最小生成树!


这个算法的核心思想就是贪心。

它的实现是这样的:

首先,我们随便拿出一个无向图:

既然要它的权值和最小,那么我们肯定先选权值最小的一条边

然后再找第二小的边

第三

第四

第五

第六

到了第七小的边时,你会发现它的两个端点已经是连通的了,再选就成一个环了,于是我们跳过它

第八

这时,我们选的边数已经达到了 \(n\) - \(1\) 条边,且图内所有的点都连通了。

因为我们每次选的边都是最小的,所以权值和也肯定是最小的,那么这张图中被标红的边就是这张图的最小生成树

于是,代码策略就出来了:

1.定义一个结构体存储每一条边的两个端点和权值。

2.将每一条边按照权值从小到大排序。

3.枚举边,用并查集来维护连通性,如果这条边的两个端点在一个集合中,那么跳过它,反之,则将它们连起来,并且把权值和 \(ans\) 加上这条边的权值,选过的边 \(cnt\) + \(1\)(注意,这里的并查集是不用管它原来所有的边的,只管你选了的边,所以它们一开始都不连通)。

4.枚举的过程中,如果你已经选了 \(n\) - \(1\) 条边,那么停止循环。

5.如果最后选过的边不足 \(n\) - \(1\) 条,那么这个图不连通,没有最小生成树,反之则有,它的权值和就是统计过的 \(ans\)。

6.耶!我们做完了!!!

至于它的证明吗,在上面,自己找

-2.这个算法有什么用啊啊啊

这个东东可以用来解决如何用最小的“代价”用 \(n\) - \(1\) 条边连接 \(n\) 个点的问题。

-3.板子题屑讲

震惊全世界的板子题 P3366 【模板】最小生成树《真》板子,都给你标了

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

分析

这有什么好分析的!就是个硬得不能再硬的板子!!!

代码(SSSSSSSVIP版含注释不纯享代码)

#include<bits/stdc++.h>
using namespace std;
const int M = 2e5 + 5, N = 5e3 + 5;
struct node//存储每一条边的结构体
{
	int x, y, w;
}a[M];
int n, m, fa[N], ans, cnt;//n个结点,m条无向边,fa[i]表示第i个节点所在的集合,ans为权值和,cnt为选的边数
int find(int x)//路径压缩
{
	if (fa[x] == x)
		return x;
	return fa[x] = find(fa[x]);
}
void merge(int x, int y)//合并
{
	int fx = find(x), fy = find(y);
	if (fx == fy)
		return;
	fa[fy] = fx;
	return;
}
void kruskal()//Kruskal
{
	for (int i = 1; i <= n; i++)//并查集初始化
		fa[i] = i;
	for (int i = 1; i <= m; i++)
	{
		int fx = find(a[i].x), fy = find(a[i].y);//找到边i的两个端点x,y所在的集合(连通块)
		if (fx != fy)//如果不在同一个集合(也就是不连通)
		{
			merge(fx, fy);//合并
			cnt++, ans += a[i].w;//边数+1,权值和+边权
		}
		if (cnt == n - 1)//如果已经选了n-1条边了,结束循环
			return;
	}
	return;
}
bool cmp(node x, node y)
{
	return x.w < y.w;
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
		cin >> a[i].x >> a[i].y >> a[i].w;
	sort(a + 1, a + 1 + m, cmp);//排序
	kruskal();//开始Kruskal
	if (cnt != n - 1)//如果不连通,输出"orz"
	{
		cout << "orz";
		return 0;
	}
	cout << ans;//输出答案
	return 0;
}

-4.早就该讲的时间复杂度

排序最慢,\(O(mlogm)\),所以总时间复杂度 \(O(mlogm)\),大大滴快!!!

-5.经典大练习卷题

P2872 Building Roads S

P1546 最短网络

P2330 繁忙的都市

P2820 局域网

P1195 口袋的天空

P1396 营救

P1194 买礼物

P2121 拆地毯

P4047 部落划分

-6.总结

因为你学好了Kruskal最小生成树、Kruskal最小生成树、Kruskal最小生成树等高级算法,所以你才能学好Kruskal最小生成树,学好了Kruskal最小生成树,你就能学好Kruskal最小生成树,你学好了Kruskal最小生成树,所以恭喜你,你学好了Kruskal最小生成树!!!

标签:连通,int,Kruskal,最小,生成,从零开始,权值
From: https://www.cnblogs.com/UchihaTsuki/p/Kruskal-Minimum-Spanning-Tree.html

相关文章

  • 力扣---64. 最小路径和
    给定一个包含非负整数的mxn网格grid,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。说明:每次只能向下或者向右移动一步。示例1:输入:grid=[[1,3,1......
  • 209. 长度最小的子数组 (Medium)
    问题描述209.长度最小的子数组(Medium)给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsₗ,num......
  • Arduino Uno + ESP-01S连接阿里云物联网平台从零开始搭建(更新中)
    简介22年10月24日我开始尝试用ArduinoUno+ESP-01S与阿里云物联网平台通信,22年11月2日基本完成。现在是23年的3月6日,我打算写成指南。我的基础是上过一个48学时的课,这......
  • 经典dp之字符串最小编辑距离
    经典dp之字符串最小编辑距离模板题给定两个串a,b,然后有3个操作:增加任意一个字母,删除任意一个字母,改变某个字母,然后问将a变成b要多少次操作这位大佬已经讲得很详细了\(f......
  • debian最小化+sway安装记录
    最小化安装debian(基于虚拟机kwm安装,gui界面virt-manager)因为虚拟机安装,虚拟机中粘贴复制命令操作不方便,安装ssh服务器便于操作,其它皆未安装。安装完成后配置ssh允许roo......
  • C语言:最大公约数和最小公倍数
    #include<stdio.h>//求任意两个数的最小公倍数main(){inta,b,i;scanf("%d%d",&a,&b);for(i=a;i<=a*b;i++)if(i%a==0&&i%b==0){......
  • 154. 寻找旋转排序数组中的最小值 II (Hard)
    问题描述154.寻找旋转排序数组中的最小值II(Hard)已知一个长度为n的数组,预先按照升序排列,经由1到n次旋转后,得到输入数组。例如,原数组nums=[0,1,4,4,5,6,7]......
  • 最小生成树(Kruskal & Prim)
    最小生成树定义对于一个带权连通无向图G=(V,E),生成树不同,每棵树的权(树中所有边上的权值和)也不同,设R为G的所有生成树的集合,若T为R中权值和最小的生成树,则T称为G的最小生成......
  • kmp 与最小循环节
    题目:一个字符串的前缀是从第一个字符开始的连续若干个字符,例如abaab共有5个前缀,分别是a,ab,aba,abaa,abaab。我们希望知道一个N位字符串S的前缀是否具有循环节。......
  • linux最小化安装后添加图形界面
    linux支持图形界面,如果装成了最小化系统该怎样添加图形界面呢?首先要知道的是,要想从最小化安装到图形界面绝对要装很多包,我们不可能一个包一个包的去装,大多数小伙伴应该也记......