最小生成树专题1 最小生成树-Prim算法


最小生成树专题1 最小生成树-Prim算法

原创 已于 2023-10-26 14:46:53 修改 · 粉丝可见 · 123 阅读 · 0 · 0 · 本内容遵循CC 4.0 BY-SA版权协议 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/134054687

题目:

样例1:

cobol<br/>4 5<br/>0 1 3<br/>0 2 2<br/>0 3 3<br/>2 3 1<br/>1 2 1<br/>
4

样例2:

cobol<br/>3 1<br/>0 1 1<br/>
-1

思路:

Prim算法和 朴素版的 Dijkstra 有点类似,也叫做 朴素版Prim算法,但也还是有点区别。

Dijkstra 中,只要起点到目的点的最短距离。

最小生成树,表示   不定某个起点和终点,要求遍历完所有点的 最短距离。

所以,朴素版的 Prim 和 朴素版的 Dijkstra 很相似。

区别在于更新 dist 的时候,Dijkstra 更新的是距离,Prim 更新的是集合之间的最短边。

1
2
3
4
for(int j = 0;j < n;++j)
{
dist[j] = min(dist[j],g[t][j]);
}

最小生成树中,是 找 集合到集合之间的  最小边,  Dijkstra最短距离是 节点之间的最小距离。

代码详解如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define YES puts("YES")
#define NO puts("NO")
#define INF 0x3f3f3f3f
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 500 + 10;

int n,k;

int g[N][N]; // 存储结点之间的最短边
bool st[N]; // 标记是否遍历过该点
int dist[N]; // 存储集合之间的最短边

inline int Prim()
{
// 初始化集合之间的最短边方案为无穷
memset(dist,INF,sizeof dist);
dist[0] = 0; // 初始化检查起始点最短边方案为 0

int ans = 0; // 存储最小生成树的最短边

for(int i = 0;i < n;++i)
{
int t = -1; // 探头 t 探索每个结点,哪个是最短边
for(int j = 0;j < n;++j)
{
// 如果符合 最短边结点,且为遍历过该结点 那么更新 t
if(!st[j] && (t == -1 || dist[j] < dist[t]))t = j;
}

// 如果存在孤立点 那么肯定无法遍历完所有点,没有最小生成树返回 -1
if(i && dist[t] >= INF) return -1;

st[t] = true; // 标记好已经遍历了 该 t 结点

if(i) ans += dist[t]; // 如果已经开始走动了,那么开始存储集合之间的最短边

for(int j = 0;j < n;++j) dist[j] = min(dist[j],g[t][j]); // 更新所有最短边,即 t 点到 j 点之间的最短边
}
if(ans >= INF) return -1; // 如果存在孤立点,返回 -1
return ans; // 返回最小生成树最短边
}

inline void solve()
{
// 初始化集合之间的边长为无穷
memset(g,INF,sizeof g);

cin >> n >> k;
while(k--)
{
int a,b,c;
cin >> a >> b >> c;
// 存储结点之间最短边
g[a][b] = g[b][a] = min(g[a][b],c);
}
cout << Prim() << endl;
}

int main()
{
// freopen("a.txt", "r", stdin);
IOS;
int _t = 1;
// cin >> _t;
while (_t--)
{
solve();
}

return 0;
}

最后提交:


觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭

微信二维码

wechat pay

支付宝二维码

ali pay

最小生成树专题1 最小生成树-Prim算法
http://blog.angindem.cn/2023/10/26/Angindem-CSDN博客/099_99/
作者
Angindem
发布于
2023年10月26日
许可协议