最小生成树--Prim算法和Kruskal算法

最小生成树Prim算法和Kruskal算法 最小生成树Prim算法和Kruskal算法实验报告1.问题2.解析1.Prim算法2.Kruskal算法3.设计Prim算法:Kruskal算法:4.分析Pime算法:Kruskal算法:5.源码 实验报告 课程名称 《算法分析与设计》 实验日期 2021年 3月8日 至 2021年 3 月15日 学生姓名 钟恺 所在班级 软工192 学号 2019212212265 实验名称 最小生成树Prim算法和Kruskal算法 实验地点 精思苑2号楼208 阅读详情

概述

Prim算法和Kruskal算法,是用来求加权连通图的最小生成树的算法。

意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。

—————————————————————————————————————————————————————————————————————————————

Prim算法

基本思想

从单一顶点开始,普里姆算法按照以下步骤逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点。

  1. 输入:一个加权连通图,其中顶点集合为V,边集合为E;

  2. 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {};

  3. 重复下列操作,直到Vnew = V:

    1. 在集合E中选取权值最小的边(u, v),其中u为集合Vnew中的元素,而v则是V中没有加入Vnew的顶点(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

    2. 将v加入集合Vnew中,将(u, v)加入集合Enew中;

  4. 输出:使用集合Vnew和Enew来描述所得到的最小生成树。


示例:

 说明不可选可选已选
Prim Algorithm 0.svg此为原始的加权连通图。每条边一侧的数字代表其权值。---
Prim Algorithm 1.svg顶点D被任意选为起始点。顶点A、B、E和F通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。C, GA, B, E, FD
Prim Algorithm 2.svg下一个顶点为距离D或A最近的顶点。B距D为9,距A为7,E为15,F为6。因此,F距D或A最近,因此将顶点F与相应边DF以高亮表示。C, GB, E, FA, D
Prim Algorithm 3.svg算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。CB, E, GA, D, F
Prim Algorithm 4.svg在当前情况下,可以在C、E与G间进行选择。C距B为8,E距B为7,G距F为11。E最近,因此将顶点E与相应边BE高亮表示。无C, E, GA, D, F, B
Prim Algorithm 5.svg这里,可供选择的顶点只有C和G。C距E为5,G距E为9,故选取C,并与边EC一同高亮表示。无C, GA, D, F, B, E
Prim Algorithm 6.svg顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG。无GA, D, F, B, E, C
Prim Algorithm 7.svg现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。无无A, D, F, B, E, C, G

算法实现:

#include<iostream>
using namespace std;

const int INF = 999999;
const int MAXV = 10000;
int vnum, edgenum, start;

// 邻接矩阵 
int edge[MAXV][MAXV];
// 记录Vnew中每个点到V中邻接点的最短边
int lowcost[MAXV];
// 标记某点是否加入Vnew
int addVnew[MAXV];
// 记录V中与Vnew最邻近的点
int adj[MAXV];

void prim(int start)
{
	// 最小生成树的权值 
	int sumweight = 0;
	int i, j;
	int k = 0;
	for(i=1;i<=vnum;++i)
	{
		lowcost[i] = INF;
		adj[i] = start;		
	}
	// 顶点从1开始 
	for(i=1;i<=vnum;++i)
	{
		// 将所有点至于Vnew之外,V之内
		// 这里只要addVnew对应的值为-1,就表示在Vnew之外
		lowcost[i] = edge[start][i];
		addVnew[i] = -1;
	}
	// 将起始点start加入Vnew
	addVnew[start] = 0;
	adj[start] = start;
	for(i=1;i<=vnum;++i)
	{
		// 由于从start开始的,因此不需要再对第start个顶点进行处理
		if(start==i)
			continue;
		int min = INF;
		int v = -1;
		for(j=1;j<=vnum;++j)
		{
			// 在Vnew之外寻找最短路径
			if(addVnew[j]==-1 && lowcost[j]<min)
			{
				min = lowcost[j];
				v = j;
			}
		}
		if(v!=-1)
		{
			// 输出新加入的边 
			cout<<adj[v]<<" "<<v<<" "<<lowcost[v]<<endl;
			// 将v加Vnew中
			addVnew[v] = 0;
			// 计算路径长度之和
			sumweight += lowcost[v];
			for(j=1;j<=vnum;++j)
			{
				if(addVnew[j]==-1 && edge[v][j]<lowcost[j])
				{
					// 此时v点加入Vnew 需要更新lowcost
					lowcost[j] = edge[v][j];
					adj[j] = v;
				}
			}
		}
	}
	// 输出最小生成树的权值 
	cout<<sumweight<<endl;
}

int main()
{
	while(cin>>vnum>>edgenum>>start)
	{
		for(int i=1;i<=vnum;++i)
		{
			for(int j=1;j<=vnum;++j)
			{
				if(i==j)
					edge[i][j] = 0;
				else
					edge[i][j] = INF;
			}
		}
		int p, q, val;
		for(int i=1;i<=edgenum;++i)
		{
			cin>>p>>q>>val;
			edge[p][q] = val;
			edge[q][p] = val;
		}
		prim(start);
	}
	return 0;
}

测试案例:

输入

7 11 4
1 2 7
1 4 5
2 3 8
2 4 9
2 5 7
3 5 5
4 5 15
4 6 6
5 6 8
5 7 9
6 7 11

输出

4 1 5
4 6 6
1 2 7
2 5 7
5 3 5
5 7 9
39



————————————————————————————————————————————————————————————————————————————

Kruskal算法

基本思想:

按照权值从小到大选择n-1条边,且保证这n-1条边不形成回路。

首先构造一个只含有n个顶点的森林,然后依照权值从小到大从联通网中选择边加入到深林中,并使森林不产生回路,直至森林变成一棵树为止。


示例:



要点:

1)对图的所有边按照权值从小到大进行排序

解决方法:采用排序算法进行排序

2)将边添加到最小生成树中时,判断是否形成了回路

解决方法:记录顶点在最小生成树中的终点,然后每次需要将一条边添加到最小生成树时,判断该边的两个顶点的终点是否重合,重合的话会构成回路。


伪代码:

Kruskal()
{
    对边的权值从小到大进行排序;
    初始化每个顶点的终点为它自己;
    对于所有的边(u,v):
        找到顶点u的终点x;
        找到顶点v的终点y;
        如果(x!=y):
            将边(u,v)加入到最小生成树中;
            修改顶点u的终点;
}

算法实现:

#include<iostream>
#include<algorithm>
using namespace std;
// 最大边的数量 
const int MAXE = 20000;
// 最大顶点的数量
const int MAXV = 20000; 
// 边的结构体 
struct edge
{
	int u, v, cost;
};

// 数组,用来保存所有的边 
edge road[MAXE];
// 数组,用来保存对应顶点的终点 
int endpoint[MAXV];

// sort需要的比较函数 
bool cmp(const edge &e1, const edge &e2)
{  
    return e1.cost<e2.cost;  
}

// find函数返回顶点x的终点 
int find(int x)
{  
    if (endpoint[x] == x) return x;  
    else return endpoint[x] = find(endpoint[x]);  
}  

// unite函数的结果是将顶点x和顶点y加入到最小生成树中 
void unite(int x, int y)
{  
    x = find(x);  
    y = find(y);  
    // 终点一样则不发生变化 
    if (x == y) return;  
    // 否则,修改x的终点为y 
    else endpoint[x] = y;  
}  

// init函数的结果是将所有顶点的终点初始化为自己 
void init(int vexnum)
{
	for(int i=0;i<vexnum;++i)
		endpoint[i] = i;
}

int KRUSKAL(int vexnum, int edgenum)
{
	// ans用于记录最小生成树的总权值 
	int ans = 0;
	// 初始化每个顶点的终点为它自己
	init(vexnum);
	//  对边的权值从小到大进行排序
	sort(road, road+edgenum, cmp);
	for(int i=0;i<edgenum;i++){  
        if(find(road[i].u)!=find(road[i].v)){  
        	// 将边(u,v)加入到最小生成树中
            // 修改顶点u的终点;
            unite(road[i].u, road[i].v);  
            ans += road[i].cost;  
        }  
    }
	return ans;
}

int main()
{
	int vexnum, edgenum;
	cin>>vexnum>>edgenum;
	for(int i=0;i<edgenum;++i)
	{
		cin>>road[i].u>>road[i].v>>road[i].cost;
	}
	cout<<KRUSKAL(vexnum, edgenum)<<endl;
	return 0;
}

测试案例:

输入

7 11
0 1 7
0 3 5
1 2 8
1 3 9
1 4 7
2 4 5
3 4 15
3 5 6
4 5 8
4 6 9
5 6 11

输出

39

参考资料:

维基百科、如果天空不死--博客园、华山大师兄--博客园

最小生成树——kruskal算法和prim算法 1.最小生成树定义 在一张带权的无向连通图中,各边权和最小的一颗生成树即为最小生成树。 2.最小生成树的应用价值 在现实生活中,很多布线问题,通线网络等问题,都可以直接或者间接的转化成最小生成树的问题去给出花费最小的方案。 3.计算最小生成树的两种算法 计算最小生成树可以采用两种方式,即Kruscarl算法和Prim算法。这两种算法都采用了贪心策略。 看过的一本书上解释说,这两... 阅读详情

相关推荐

图论之最小生成树 Prim算法和Kruskal算法

1.最小生成树问题 最小生成树问题:一个图有V个顶点,找到V-1条边连接这V个顶点,使得总权值最小 最小生成树问题通常是针对带权无向图、连通图 如果图不是连通图:分别在每个连通分量上计算最小生成树---最小生成森林 应用:电缆布线设计、网络设计、电路设计 ...

与 1644

数据结构(四)—— 图(4):最小生成树问题

4. 最小生成树问题4.1 什么是最小生成树4.2 贪心算法4.2.1 Prim算法4.2.2 Kruskal算法4.3 最小树生成问题的实现4.3.1 Prim算法的实现4.3.2 Kruskal算法的实现 4. 最小生成树问题 4.1 什么是最小生成树   一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。   最小生成树(Minimum Spanning .

大彤小忆的博客 2997

最小生成树的prim算法和kruskal算法

Prim 算法思想: 从任意一顶点 v0 开始选择其最近顶点 v1 构成树 T1,再连接与 T1 最近顶点 v2 构成树 T2, 如此重复直到所有顶点均在所构成树中为止。 最小生成树(MST):权值最小的生成树。 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路。可以把边上的权值解释为线路的造价。则最小生成树表示使其造价最小的生成树。 构造网的最小生成树必须解决下面两个问题: 1、尽可能选取权值小的边,但不能构成回路; 2、选取n-1条恰当的边以连通n个顶点; MST性质:假设G=(V,E)是一个

weixin_45950208的博客 477

图论算法——Prim算法和Kruskal算法

引言 我们要学习的第一种计算最小生成树的算法,它每一步都会为一颗生长中的树添加一条边。 下面分析下算法思路 思路 一开始这棵树只有一个顶点,然后会向它添加V-1条边,每次总是将下一条连接树中的顶点与不在树中的顶点且权重最小的边加入树中。 每次当我们向(生成)树中添加了一条边之后,也向树中添加了一个顶点。要维护一个包含所有横切边的集合,就要将连接这个顶点和其他所有不在树中的顶点的边加入优先队列。要注...

日积月累,天道酬勤 1732

【KBrowser】基于 Kiwi/chromium 制作全新外壳,将 chromium 代码当作 webview 使用,实现可控核替换

chromium 其实只需几步巧妙的架构,就能拿来“换核”,甚至可以插件化,实现类似webview.apk 的效果。重新设计界面,不再是差不多的回声。而 Kiwi 基于 chrome 77 ,只有 50 MB。优势是兼容好、可安装扩展。

sinat_27171121的博客 2029

LSCM最小二乘保角参数化

LSCM最小二乘保角参数化 最小二乘思想 已知一组点的数据(x,y) x x1x_1x1​ x2x_2x2​ x3x_3x3​ … xnx_nxn​ y y1y_1y1​ y2y_2y2​ y3y_3y3​ … yny_nyn​ 可以近似为线性关系 y=ax+by=ax+by=ax+b ,目标为确定常数 aaa , bbb ; 解法:找到 aaa , bbb ,使得所有 yiy_iyi​ 与 axi+bax_i+baxi​+b 偏差的平方和 Q=∑i=1n(yi−axi−b)2 Q=\s

weixin_49732532的博客 4252

858. Prim算法求最小生成树

给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环,边权可能为负数。 求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible。 给定一张边带权的无向图 G=(V,E),其中 V 表示图中点的集合,E 表示图中边的集合,n=|V|,m=|E|。 由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G 的最小生成树。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行,每行包含三个整数

qq_45638271的博客 582

Innovus Function ECO实战:5步搞定数字后端设计中的网表修正(含Calibre LVS验证技巧)

本文提供了一份完整的Innovus Function ECO实战指南,详细解析了数字后端设计中网表修正的五步流程。从理解Function ECO概念、准备关键文件,到在Innovus中执行逻辑比对、自动布线及GUI检查,并重点攻克了ECO后Calibre LVS验证的难点与调试技巧,帮助工程师高效、精准地完成流片前的设计微调。

day7的博客 949

图论算法—最小生成树的Prim算法和Kruskal算法原理解析以及Java代码的实现

介绍了图的最小生成树的概念以及求最小生成树的两种算法:Prim算法和Kruskal算法的原理,最后提供了基于邻接矩阵和邻接链表的图对两种算法的Java实现。

终生学习践行者 7832

wifi/BT芯片RTL8723DS驱动移植和测试之一wifi篇

本文主要介绍如何在stm32mp157中移植并测试芯片RTL8723DS的wifi功能。

汉尼拔勇闯天涯 8741

防止加入域主机脱离域的控制(管理员权限)

一、简介   当公司所有主机加入到域后,SA首要工作就是防止加入域的主机脱离域的控制。让我发现该工作的必要性是一程序猿,前一天刚配完禁止执行QQ、微信执行,第二天就看到那家伙在用微信聊天,肯定是用回旧的本地账号登陆了。   本人所在公司安装软件的类型繁杂,无管理员权限运行不少软件会报错,不得不授予「域账号」本地管理员权限。过大的权限带也来了一系列后果:用户可随意退出域、创建本地管理员...

der69615的博客 3174

Prim算法和Kruskal算法C++代码实现

【代码】Prim算法和Kruskal算法C++代码实现(高级算法分析与设计课程论文实验代码)

xin3157的博客 626

新手必看:手把手教你如何通过Github提交CVE漏洞(附完整截图流程)

本文为安全研究新手提供了一份详尽的CVE漏洞提交实战指南。文章重点介绍了如何通过Github平台,从漏洞发现、验证、撰写专业报告到最终提交CVE申请的全流程,并附有完整的截图和沟通模板,帮助初学者迈出负责任漏洞披露的第一步。

ttt77的博客 1253

最小生成树—Kruskal算法和Prim算法

求图的最小生成树的两种算法Kruskal算法和Prim算法解析

终为nullptr 2279

45.qt quick-qml虚拟软键盘详解(一)

1.qml虚拟键盘介绍 Qt虚拟键盘的主要功能包括: 可定制的键盘布局和风格与动态切换。 带有单词选择的预测性文本输入。 角色预览和替代角色视图。 自动大小写和空格插入。 不同分辨率的可伸缩性。 支持不同的字符集(拉丁,简体/繁体中文,印地语,日语,阿拉伯语,希伯来语,韩语和其他)。 支持大多数常见的输入语言,可以轻松扩展语言支持。 从左到右和从右到左的输入。 硬件键支持2路和5路导航。 手写支持,带有全屏输入的手势。 音频反馈。 跨平台功能。 支持多国语言,高达40多个语言 本

抵抗时间扭曲,坚持做一件有意义的事 3560

Qt实现离线缓存地图(附完整源码)

Qt实现离线缓存地图(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 857

图解最小生成树问题:Kruskal算法和Prim算法

本文全面介绍了两类经典算法,用于解决无向图中的最小生成树(MST)问题。文章解释了最小生成树的概念,并详细对比分析了Kruskal和Prim两种算法的原理、特点及应用场景。文章重点以图文并茂的方式,通过示例演示了算法的执行过程,包括详细的步骤解析和权值图示。Kruskal算法侧重边的逐步加入,适用于稀疏图;Prim算法侧重点的逐步扩张,适用于稠密图。两者均采用贪心策略,在网络设计、电路布线等领域有着广泛的应用。

m0_74496615的博客 2696

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

最小生成树-Prim算法和Kruskal算法

Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗

不积跬步无以至千里 10万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

最小生成树之Kruskal和Prim算法——C++实现

很久以前就学过最小生成树之Kruskal和Prim算法,这两个算法很容易理解,但实现起来并不那么容易。最近学习了并查集算法,得知并查集可以用于实现上述两个算法后,我自己动手实现了最小生成树算法。 宏观上讲,Kruskal算法就是一个合并的过程,而Prim算法是一个吞并的过程,另外在Prim算法中还用到了一种数据结构——优先级队列,用于动态排序。由于这两个算法很容易理解,在此不再赘述。接下来给出我

疯狂的指针的博客 1万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【最小生成树】Prim算法和Kruskal算法的区别对比

Prim算法和Kruskal算法都是从连通图中找出最小生成树的经典算法~ 从策略上来说,Prim算法是直接查找,多次寻找邻边的权重最小值,而Kruskal是需要先对权重排序后查找的~ 所以说,Kruskal在算法效率上是比Prim快的,因为Kruskal只需一次对权重的排序就能找到最小生成树,而Prim算法需要多次对邻边排序才能找到~ Prim算法的实现过程 首先以一个结点作为最小生成树的...

柳婼 の blog 3万+

C语言实现最小生成树算法:Prim和Kruskal

【代码】C语言实现最小生成树算法:Prim和Kruskal。

我滴小博客 1731

最小生成树:Prim算法和Kruskal算法

由于Kruksal算法是对边进行操作,先取出边,然后判断边的两个节点,这样的话,如果一个图结构非常的稠密,那么Kruksal算法就比较慢了,而Prim算法只是对节点进行遍历,并使用set进行标记,因此会相对于Kruksal算法,在稠密图方面好很多,因此。Kruskal算法也是一种贪心算法,它将图中所有边按照权值从小到大排序,然后从权值最小的边开始,每次选择一条不构成环路的边加入到生成树中,直到所有顶点都被加入。如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 `orz`。

Blueis_oss的博客 1331

用Prim和Kruskal两种算法,求解最小生成树

用Prim和Kruskal两种算法,求解最小生成树,给出模板题以及解题代码。

青春无问西东 岁月自成芳华 4144

最小生成树——Prim算法和Kruskal算法详解

最小生成树 对于一个带权连通无向图G=(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同,设r为G的所有生成树的集合,若T为r中边的权值之和最小的那棵生成树,则T称为G的最小生成树。 最小生成树的性质: 最小生成树不是唯一的。 最小生成树的边的权值之和总是唯一的 最小生成树的边数为顶点数减1,即边数=n-1(n为顶点数) 下面介绍两种实现最小生成树的算法: 普里姆(Prim)算法 Prim算法的执行非常类似于寻找图的最短路径的Dijkstra算法。 基...

mustach的博客 4001

Prim算法和Kruskal算法求最小生成树

AcWing 858. Prim算法求最小生成树 给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。 求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。 给定一张边带权的无向图G=(V, E),其中V表示图中点的集合,E表示图中边的集合,n=|V|,m=|E|。 由V中的全部n个顶点和E中n-1条边构成的无向连通子图被称为G的一棵生成树,其中边的权值之和最小的生成树被称为无向图G的最小生成树。 输入格式 第一行包含两个整数n和m。 接下来m行,每行包含三个整数u

Quorra_chord的博客 1459

图论算法总结:最小生成树的两种算法 Prim和Kruskal算法

求解最小生成树的两种算法 Prim和Kruskal算法(附代码和思路)

2301_81494395的博客 1334
上一篇: 排序算法总结
下一篇: 单链表及双链表总结
Nim的辙迹
博客等级 码龄10年 17粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值