当前位置: 首页 > article >正文

【算法】Prim最小生成树算法

目录

一、思想

二、代码


在阅读本文前推荐优先食用:

【算法】Kruskal最小生成树算法-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Eristic0618/article/details/143312482?spm=1001.2014.3001.5501

一、思想

Kruskal算法基于边的选择,因此更适用于稀疏图。而对于基于选择节点的Prim最小生成树算法,其更适用于边数量远大于节点数量的稠密图

Prim算法的思想如下:

  • 选择一个起始点作为连通块的一部分,更新其他节点距离连通块的最短距离
  • 每次选择离连通块距离最短的节点,将其加入连通块,并更新其他节点距离连通块的最短距离
  • 重复上一步,直到所有节点都包含在连通块内,构成一颗最小生成树

例如下面这个图:

我们以1号节点作为起始节点加入连通块,其他所有节点距离连通块的距离初始化为最大值

更新其他节点距离连通块的最短距离

从所有没有被加入连通块的节点中,找出离连通块距离最短的节点(此处为V3),加入连通块

更新其他节点距离连通块的最短距离,因为V3是新加入连通块的节点,所以实际上只需要判断其他未加入节点距离V3的距离是否小于自己原来的最短距离即可

继续找距离最短节点,此处V4和V6距离连通块的距离都为4,说明最小生成树不一定是唯一的。此处我们选择V4,将其加入连通块并更新距离

V6距离连通块最近,将V6加入连通块并更新距离

V2最近,将V2加入连通块并更新距离

最后是V5

所有节点都被加入连通块后,我们就得到了图中的最小生成树


二、代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define debug(x) cout << #x << " = " << x << '\n'
#define INF 0x3f3f3f3f
using namespace std;

#define N 510
#define M 1000010

int	n, m;
int dist[N]; //节点到连通块的最短距离 
int g[N][N]; //邻接矩阵
bool st[N];  //判断某节点是否在连通块中 

int Prim()
{
	memset(dist, 0x3f, sizeof dist); //初始化dist数组 
	dist[1] = 0;
	
	int res = 0; //最小生成树边权和 
	for(int i = 0; i < n; i++) //起始节点已加入连通块,遍历剩余n-1个节点
	{
		int t = -1; //标记当前遍历中与连通块距离最小的节点编号 
		for(int j = 1; j <= n; j++) //遍历所有节点 
		{
			if(!st[j] && (t == -1 || dist[t] > dist[j])) //节点j不在连通块中 且 当前未选择节点或节点j距离比节点t更短
				t = j; //更新t 
		}
		//经过循环,此时节点t就是 剩余所有不属于连通块中的节点 中 距离连通块最短的节点 
		if(dist[t] > INF / 2) return INF; // dist[t]仍为最大值,说明剩余节点不与连通块相连
		
		res += dist[t]; //将t距离连通块的距离加入边权和 
		
		for(int j = 1; j <= n; j++)
		{
			dist[j] = min(dist[j], g[t][j]); //更新剩余节点到连通块的最短距离 
		}
		
		st[t] = true; //将节点t加入连通块 
	}
	return res;
}

void solve()
{
	cin >> n >> m;
	
	memset(g, 0x3f, sizeof g); //所有权重全部初始化为最大值 
	for(int i = 0;i < m; i++)
	{
		int a, b, w;
		cin >> a >> b >> w;
		g[a][b] = g[b][a] = min(g[a][b], w); //无向图and可能存在重边 
	}
	
	int ret = Prim();
	
	if(ret == INF) cout << "impossible" << endl;
	else cout << ret << endl;
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    //cin >> t;
    while(t--)
        solve();
    return 0;
}

完.


http://www.kler.cn/a/380308.html

相关文章:

  • ELK 使用教程采集系统日志 Elasticsearch、Logstash、Kibana
  • 【开源社区openEuler实践】rust_shyper
  • 树莓派4b如何连接ov7670摄像头
  • 如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?
  • TI毫米波雷达原始数据解析之Lane数据交换
  • 将 Docker 数据迁移到新磁盘:详细操作指南
  • 【k8s】-运维技巧-1
  • Spring Boot实战:构建校园社团信息管理系统
  • Linux基础(七):Linux文件与目录管理
  • 软件加密与授权管理:构建安全高效的软件使用体系
  • docker镜像获取不到的问题处理
  • TIDB的结构
  • 【SpringCloud详细教程】-01-一文了解微服务
  • Python和MATLAB都可以用于绘制折线图,下面是分别用Python和MATLAB绘制简单折线图的示例。
  • 蓝桥双周赛 第21场 小白入门赛
  • 【每日 C/C++ 问题】
  • mac 打开访达快捷键
  • 一二三应用开发平台自定义查询设计与实现系列3——通用化重构
  • linux mysql8大小写敏感问题
  • Spring Boot框架在信息学科平台开发中的高级应用
  • SpringBoot在线教育系统:集成第三方服务
  • AWTK文件系统适配器更新-支持RT-Thread DFS POSIX接口
  • Java中的线程安全问题(如果想知道Java中有关线程安全问题的基本知识,那么只看这一篇就足够了!)
  • Java项目实战II基于Java+Spring Boot+MySQL的体育馆使用预约平台的设计与实现(源码+数据库+文档)
  • flask websocket服务搭建,flask-sock 和 flask-socketio
  • 开源 AI 智能名片 2+1 链动模式 S2B2C 商城小程序与私域流量圈层