最小生成树prim算法详解

embedded/2024/10/18 5:37:59/

prim算法解决的是最小生成树问题,即在一个给定的无向图G中求一棵生成树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权之和最小。

prim算法的基本思想是对图G设置集合S来存放已被访问的顶点,然后执行n次下面的两个步骤:

(1)每次从集合V-S中选择与集合S最近的一个顶点(记为u),访问u并将其加入集合S,同时把这条离集合S最近的边加入到最小生成树中。

(2)令顶点u作为集合S与集合V-S连接的接口,优化从u能到达的未访问顶点v与集合S的最短距离

prim算法和Dijkstra算法使用的思想几乎完全相同。只有在数组d[]的含义上有所区别。其中,Dijkstra算法的数组d[]含义为起点s到达顶点Vi的最短距离,而prim算法的数组d[]含义为顶点Vi与集合S的最短距离,两者的区别仅在于最短距离是顶点Vi针对“起点s”还是“集合S”。另外,对最小生成树问题而言,如果仅是求最小边权之和,那么在prim算法中就可以随意指定一个顶点为初始点,例如在下面的代码中默认使用0号顶点为初始点。实现的伪代码如下:

Prim(G,d[]){初始化;for(循环n次){u=使d[u]最小的还未被访问的顶点的标号;记u已被访问;for(从u出发能到达的所有顶点v){if(v未被访问&&以u为中介点使得v与集合S的最短距离d[v]更优){将G[u][v]赋值给v与集合S的最短距离d[v]; }} } 
}

下面给出分别使用邻接矩阵和邻接表的prim算法代码:

(1)邻接矩阵版

const int maxn=1000;
const int INF=1000000000;
int n,G[maxn][maxn];
int d[maxn];
bool vis[maxn]={false};
int prim(){//默认0为起始点,函数返回最小生成树的边权之和 fill(d,d+maxn,INF);d[0]=0;int ans=0;for(int i=0;i<n;i++){int u=-1,MIN=INF;for(int j=0;j<n;j++){//找到未访问的顶点中d[]最小的 if(vis[j]==false&&d[j]<MIN){u=j;MIN=INF;}}if(u==-1){return -1;}vis[u]=true;ans+=d[u];for(int v=0;v<n;v++){if(vis[v]==false&&G[u][v]!=INF&&G[u][v]<d[v]){d[v]=G[u][v];}}}return ans;
}

(2)邻接表版

struct node{int v,dis;
};
vector<node> Adj[maxn];
int n;
int d[maxn];
bool vis[maxn]={false};
int prime(){fill(d,d+maxn,INF);d[0]=0;int ans=0;for(int i=0;i<n;i++){int u=-1,MIN=INF;for(int j=0;j<n;j++){if(vis[j]==false&&d[j]<MIN){u=j;MIN=d[j];}}if(u==-1){return -1;}vis[u]=true;ans+=d[u];for(int j=0;j<Adj[u].size();j++){int v=Adj[u][j].v;if(vis[v]==false&&Adj[u][j].dis<d[v]){d[v]=Adj[u][j].dis;}}}return ans;
}

和Dijkstra算法一样,使用这种写法的复杂度为O\left ( V^{2} \right ),其中邻接表实现的prim算法可以使用堆优化使时间复杂度降为O\left ( VlogV+E \right )。所以尽量在图的顶点数目较少而边数较多的情况下使用prim算法


http://www.ppmy.cn/embedded/48596.html

相关文章

力扣刷题总结 -- 数组26

76. 所有奇数长度子数组的和&#xff08;简单&#xff09; 题目要求&#xff1a; 给定一个正整数数组 arr &#xff0c;计算所有奇数长度子数组的和。 子数组定义为原数组中的一个连续子序列。 返回 arr 中 所有奇数长度子数组的和 。 题目分析&#xff1a; 先得到所有子…

k-means聚类模型的优缺点

一、k-means聚类模型的优点 1. 简单高效&#xff1a;k-means算法思想简单直观&#xff0c;易于实现。它通过迭代计算样本点与聚类中心之间的距离&#xff0c;并不断调整聚类中心的位置&#xff0c;直至满足终止条件。由于其计算过程相对直接&#xff0c;所以具有较高的执行效率…

基于YOLOv10深度学习的高密度人脸智能检测与统计系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Python中的“*”和“**”

1.接受任意长度形参&#xff0c;组成turple def function(*args):# type(args)turple# args(1, 2, 3, 4)print(args)ant0for i in range(len(args)):antargs[i]return antprint(function(1,2,3,4)) # 102.接受任意长度形参&#xff0c;组成dict def function(**args):# type…

探索Edge

目录 1.概述 1.1.什么是浏览器 1.2.浏览器的作用 2.Edge 2.1.什么是Edge 2.2.诞生背景 2.3.历史版本 2.4.作用 2.5.优缺点 2.5.1.优点 2.5.2.缺点 3.对比 3.1.和360浏览器的对比 3.2.和谷歌浏览器&#xff08;Chrome&#xff09;的对比 4.未来展望 5.总结 1.概…

【数据结构】第十五弹---C语言实现直接插入排序

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、排序的概念及其运用 1.1、排序的概念与分类 1.2、排序运用 1.3、常见的排序算法 1.4、常见的排序算法性能测试 2、常见排序算法的实现 2…

【Android】实现Recyclerview的Item可以左右侧滑动的效果

项目需要 使用Recyclerview进行列表的数据加载的时候&#xff0c;需要对这个Item进行左右滑动进行操作的功能&#xff0c; 比如这样 需求实现 上面图来源于 https://github.com/anzaizai/EasySwipeMenuLayout 这是一个可以用来进行列表左滑、右滑的项目&#xff0c;可以集…

C# WPF入门学习主线篇(三十二)—— 创建Model、View和ViewModel

C# WPF入门学习主线篇&#xff08;三十二&#xff09;—— 创建Model、View和ViewModel 在前一篇文章中&#xff0c;我们介绍了MVVM&#xff08;Model-View-ViewModel&#xff09;模式的基本概念。本篇将深入探讨如何在实际开发中创建Model、View和ViewModel&#xff0c;并通过…