最小生成树

news2024/11/8 17:03:01

文章目录

    • 基本原理
    • Kruskal算法
    • Prim算法

基本原理

连通图中的每一棵生成树,都是原图的一个极大无环子图,即:从其中删去任何一条边,生成树就不在连通;反之,在其中引入任何一条新边,都会形成一条回路。
若连通图由n个顶点组成,则其生成树必含n个顶点和n-1条边。因此构造最小生成树的准则有三条:

  1. 只能使用图中的边来构造最小生成树
  2. 只能使用恰好n-1条边来连接图中的n个顶点
  3. 选用的n-1条边不能构成回路

构造最小生成树的方法:Kruskal算法和Prim算法。这两个算法都采用了逐步求解的贪心策略。

Kruskal算法

核心思想:每次迭代时,选出一条具有最小权值,且连接后图不形成回路,加入生成树。

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

  1. 利用优先级队列记录当前最小的边
  2. 判断是否形成回路利用并查集

并查集

template<class W>
struct Edge
{
	Edge(int srci,int dsti,W w)
		:_srci(srci)
		,_dsti(dsti)
		,_w(w)
	{}
	bool operator>(const Edge& e) const 
	{
		return _w > e._w;
	}

	int _srci;
	int _dsti;
	W _w;
};
int Kruskal(self& minT)
{
	int n = _vertexs.size();
	minT._matrix.resize(n, vector<int>(n,MAX_W));

	minT._vertexs = _vertexs;
	minT._mapIndex = _mapIndex;
	unionFindSet ufs(n);
	priority_queue<Edge, vector<Edge>, greater<Edge>> pq;
	//将所有边入队列
	for (int i = 0; i < n; ++i)
	{
		for (int j = i+1; j < n; ++j)
		{
			if (_matrix[i][j] != MAX_W)
			{
				pq.push({ i,j,_matrix[i][j] });
			}
		}
	}
	int sz = 0;
	int mincount = 0;
	// 边不在一个集合,说明不会构成环,则添加到最小生成树
	while (!pq.empty() && sz < n - 1)
	{
		Edge tmp = pq.top();
		pq.pop();

		if (ufs.isSameRoot(tmp._dsti, tmp._srci) == false)
		{
			sz++;
			mincount += tmp._w;
			minT._matrix[tmp._dsti][tmp._srci] = tmp._w;

			ufs.gather(tmp._dsti, tmp._srci);
		}
	}
	if (sz != n - 1)
	{
		return -1;
	}
	return mincount;
}
void TestGraphMinTree()
{
const char* str = "abcdefghi";
Graph<char, int> g(str, strlen(str));
g.AddEdge('a', 'b', 4);
g.AddEdge('a', 'h', 8);
g.AddEdge('b', 'c', 8);
g.AddEdge('b', 'h', 11);
g.AddEdge('c', 'i', 2);
g.AddEdge('c', 'f', 4);
g.AddEdge('c', 'd', 7);
g.AddEdge('d', 'f', 14);
g.AddEdge('d', 'e', 9);
g.AddEdge('e', 'f', 10);
g.AddEdge('f', 'g', 2);
g.AddEdge('g', 'h', 1);
g.AddEdge('g', 'i', 6);
g.AddEdge('h', 'i', 7);
Graph<char, int> kminTree;
cout << "Kruskal:" << g.Kruskal(kminTree) << endl;
kminTree.print();
}

在这里插入图片描述

Prim算法

Prim与Kruskal算法类似区别在于
Kruskal算法:从整个图寻找最小的边去试
Prim算法:从某个节点出发,先找该节点相邻最小的边,每选取一个节点,将该节点所有的边入优先级队列,在选取最小的边去试

int Prim(self& minT,const V& start)
{
	int n = _vertexs.size();
	minT._matrix.resize(n, vector<int>(n, MAX_W));

	minT._vertexs = _vertexs;
	minT._mapIndex = _mapIndex;
	unionFindSet ufs(n);
	priority_queue<Edge, vector<Edge>, greater<Edge>> pq;
	int starti = findIndex(start);
	for (int i = 0; i < n; i++)
	{
		if (_matrix[starti][i] != MAX_W)
		{
			pq.push({ starti,i,_matrix[starti][i] });
		}
	}

	int sz = 0;
	int mincount = 0;


	while (!pq.empty() && sz < n - 1)
	{
		Edge tmp = pq.top();
		pq.pop();
		// 防止成环
		if (ufs.isSameRoot(tmp._dsti, tmp._srci) == false)
		{
			sz++;
			mincount += tmp._w;
			ufs.gather(tmp._dsti, tmp._srci);
			minT._matrix[tmp._dsti][tmp._srci] = tmp._w;
			// 	新入顶点的边入队列
			for (int i = 0; i < n; i++)
			{
				if (_matrix[tmp._dsti][i] != MAX_W)
				{
					pq.push({ tmp._dsti,i,_matrix[tmp._dsti][i] });
				}
			}
		}
	}
	if (sz != n - 1)
	{
		return -1;
	}

	return mincount;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二叉树9:二叉树的最大深度

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a; 104. 二叉树的最大深度 559.n叉树的最大深度 104.二叉树的最大深度 题目&#xff1a; 给定一个二叉树&#xff0…

校招面试真题 | 你的期望薪资是多少?为什么

很多人去面试的时候&#xff0c;就像打游戏&#xff0c;过五关斩六将&#xff0c;终于到最后一关了&#xff0c;但是谈薪资的难度堪比打游戏中搞定终级 boss 的难度&#xff0c;真的是太「南」了&#xff0c;好多人都是因为这个问题让自己五味杂陈呀。报高了怕好 offer 失之交臂…

Ubuntu: Docker安装与操作

在进行docker安装前&#xff0c;我们首先得有以下工具&#xff1a;xshell,FileZilla Client Xshell下载安装教程 FileZilla Client下载安装教程 如果你的Ubuntu是纯净的(也就是说刚下好并且刚用虚拟机装好的)&#xff0c;你得先 打开终端&#xff08;CtrlAltT&#xff09; 一…

远程连接服务器(运用密钥)连接winscp/vscode/mobaxterm

1.连接ssh 先检查自己是否登上校园VPN校园VPN导航页 (xjtu.edu.cn) sslvpn 进入cmd&#xff08;黑框框&#xff09; 输入&#xff1a; &#xff08;1&#xff09; ssh &#xff08;用户名&#xff09;&#xff08;IP名&#xff09; -p &#xff08;端口如22、2022&#x…

基于SSM框架的旅游网站的设计与实现

1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目&#xff0c;*基于SSM框架的旅游网站的设计与实现 *。 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 1.1.研究背景 随着互联网技术的飞速发展&#xff0c;网络与我们的生活息息相关&#xff0c;在我们日…

汉诺塔问题的时间复杂度

一、汉诺塔问题 汉诺塔&#xff08;Tower of Hanoi&#xff09;是一个经典的递归算法问题。它描述的是有三根杆子和若干个不同大小的圆盘&#xff0c;圆盘可以按照大小顺序放在杆子上。初始时&#xff0c;所有圆盘都放在左边的杆子上&#xff0c;目标是将所有圆盘移动到右边的…

PS CS6视频剪辑基本技巧(三)添加声音和字幕

上一讲&#xff0c;介绍一下视频剪接和添加图片这两个功能。这一讲介绍添加声音和字幕&#xff0c;给上一讲剪接的视频添加一个背景音乐和解说字幕。 目录 一、添加音频 1、添加背景音乐 2、剪掉多余音乐 二、添加字幕 1、制作字幕模板 &#xff08;1&#xff09;新建背…

统治扩散模型的U-Net要被取代了,谢赛宁等引入Transformer提出DiT

来自 UC 伯克利的 William Peebles 以及纽约大学的谢赛宁撰文揭秘扩散模型中架构选择的意义&#xff0c;并为未来的生成模型研究提供经验基线。 近几年&#xff0c;在 Transformer 的推动下&#xff0c;机器学习正在经历复兴。过去五年中&#xff0c;用于自然语言处理、计算机视…

【C++】STL——priority_queue的介绍和使用及模拟实现

priority_queue的介绍和使用及模拟实现 文章目录priority_queue的介绍和使用及模拟实现1.priority_queue的介绍和使用priority_queue的介绍priority_queue的使用2. 仿函数3.堆的调整算法堆的向上调整算法堆的向下调整算法4.priority_queue的模拟实现1.priority_queue的介绍和使…

史上最简单易懂的TypeScript教程(更新中)

TypeScript欢迎观看由大型东方幻想车编写的typescript教程1. TypeScript: 类型&#xff08;1&#xff09;其他类型欢迎观看由大型东方幻想车编写的typescript教程 TypeScript介绍: TypeScript是JavaScript类型的严格超集&#xff0c;它可以编译成纯JavaScript。TypeScript可以在…

基于VitePress搭建静态文档系统

文章目录前言一、快速上手二、常用配置2.1 类Vue风格首页2.2 顶部导航配置themeConfig.nav2.3 侧边栏导航设置2.3 文档中的链接跳转2.3.1 上一页与下一页2.3.2 文档中链接2.3.3 生成成员页三、进阶配置四、参考代码前言 vitePress&#xff1a;与vue press相似&#xff0c;是一…

Spring中自定义事件监听

目录 一、Spring中的事件监听 二、自定义事件监听 三、例子 1、事件 2、事件监听器 3、事件发布操作 三、测试注意 一、Spring中的事件监听 当处理完一段代码逻辑&#xff0c;后面需要同时执行多个任务&#xff0c;有什么好方法呢&#xff1f;如果在微服务项目中&…

【自用】VUE项目 宝塔部署 上线阿里云服务器CentOS7.6

一、给VUE项目打包 1.开始打包 运行命令&#xff1a; npm run build2.找到打包好的 dist 文件夹 要记住这个dist文件放在了哪儿&#xff0c;记住哦&#xff01; 二、服务器端安装宝塔面板 1.进入root用户并执行命令 yum install -y wget && wget -O install.…

Node基础——认识Node

什么是Node 首先JavaScript是一门编程语言&#xff0c;就像Java、Python、C#、GO一样&#xff0c;在Node出来之前&#xff0c;JavaScript主要运行于浏览器中&#xff0c;用来控制页面的展示逻辑&#xff0c;以及交互操作等。JavaScript之所以能够在浏览器中执行&#xff0c;是…

Docker搭建Mysql主主架构

文章目录mysql主从架构原理MySQL通用架构方案搭建步骤1. docker创建俩台mysql 端口&#xff1a;23306 和 333062. 创建my.cnf&#xff0c;并将my.cnf拷贝到docker容器中&#xff0c;并重启生效3. 配置完成&#xff0c;开始执行sql&#xff0c;设置主从主主同步mysql主从架构原理…

CSDN每日一练非负整数求和 C语言

题目名称&#xff1a;非负整数求和 时间限制&#xff1a;1000ms 内存限制&#xff1a;256M 题目描述&#xff1a; 给定两个字符串形式的非负整数 num1 和 num2 &#xff0c;计算它们的和。 注意&#xff1a; - num1 和 num2 的长度都小于 5100. - num1 和 num2 都只包含数字 0…

【圣诞节特辑】爱心代码(程序员的浪漫plus+)-李峋

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 唯有热爱&#xff0c;可抵岁月漫长&#xff0c;唯有热爱&#xff0c;不畏世间无常&#xff01; 一、前言 前段时间《点燃我温暖你》中李峋的爱心代码超级火&#xff0c;看着特别心动&#xff01;这不&#xff0c;圣…

贪心算法(Java版本)

一、贪心算法 1、算法描述 贪心算法&#xff08;Greedy algorithm&#xff09;&#xff0c;又叫做贪婪算法。 在对问题求解时&#xff0c;不从整体考虑&#xff0c;而是从问题的某一个初始解出发&#xff0c;每一步选择中都采取在当前状态下最好或最优的选择&#xff08;局部…

vcpkg踩坑记录

接触了vcpkg一段时间, 感觉在包管理方面确实很有帮助, 然而在使用中, 也碰到了各种各样的问题, 总结记录一下. vcpkg github: https://github.com/Microsoft/vcpkg 快速使用指南 To get started: > git clone https://github.com/Microsoft/vcpkg.git(也可以从下载地址直…

C语言—局部变量和全局变量

不同函数之间定义的变量是无法相互进行访问的&#xff1b; #include <stdio.h>void Test();int main() {int a 100;printf("%d", b); }void Test() {int b 200;printf("%d", a); } 在main函数中无法访问到Test中的变量b&#xff0c;同样&#xff…