最小生成树Prim算法

718 字
4 分钟
最小生成树Prim算法

最小生成树 Prim 算法#

Prim 算法用来求无向连通图的最小生成树。

最小生成树的意思是:选出一些边,把所有点连起来,并且总权重最小。

如果图不连通,就不存在最小生成树。

1、Prim 的核心思想#

Prim 像是在“不断扩展一个集合”。

刚开始生成树里只有一个点。每次从连接“树内点”和“树外点”的边里,选权重最小的一条,把新的点加入生成树。

重复这个过程,直到所有点都加入。

2、和 Dijkstra 的相似点#

Prim 和 Dijkstra 都会用到:

dist 数组
st 数组
小根堆

但含义不同:

  • Dijkstra 的 dist[j] 是起点到 j 的最短路。
  • Prim 的 dist[j] 是点 j 连接到当前生成树的最小边权。

3、什么时候更新 dist#

当一个点 p 加入生成树后,遍历它的所有邻边:

p -> j,边权 c

如果 j 还没有加入生成树,并且 c < dist[j],就更新:

dist[j] = c;

4、C++ 模板#

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;
const int M = 200010;
const int INF = 0x3f3f3f3f;
int n, m;
int h[N], e[M], w[M], ne[M], idx;
int dista[N];
bool st[N];
void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
int prim() {
memset(dista, 0x3f, sizeof dista);
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1});
dista[1] = 0;
int cnt = 0;
int ans = 0;
while (!heap.empty()) {
auto t = heap.top();
heap.pop();
int distance = t.first;
int ver = t.second;
if (st[ver]) continue;
st[ver] = true;
cnt++;
ans += distance;
for (int i = h[ver]; i != -1; i = ne[i]) {
int j = e[i];
int c = w[i];
if (!st[j] && c < dista[j]) {
dista[j] = c;
heap.push({dista[j], j});
}
}
}
if (cnt < n) return -1;
return ans;
}
int main() {
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
printf("%d\n", prim());
return 0;
}

5、为什么无向边要加两次#

如果题目给的是无向图:

a -- b

存图时要写:

add(a, b, c);
add(b, a, c);

这样从 a 能走到 b,从 b 也能走到 a。

6、怎么判断图不连通#

Prim 每次成功加入一个新点,就让 cnt++。

如果最后:

cnt < n

说明不是所有点都能被连上,图不连通,没有最小生成树。

7、容易写错的地方#

(1)边数组要开两倍#

无向图每条边存两次,所以:

const int M = 200010;

如果 m 最大是 100000,边数组至少要开 2 * m。

(2)Prim 的 dist 不是起点最短路#

它表示“连接到当前生成树的最小边权”。

(3)加入生成树时再累加答案#

ans += distance;

这个点真正被选中时,才把连接它的边权加入答案。

总结#

Prim 的关键词是:

从树外选一条最小边,把新点加入生成树

它和 Dijkstra 写法很像,但 dist 的意义不同。理解这一点,模板就不容易混。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

最小生成树Prim算法
https://blog.tjcheng.cn/posts/migrated/old-93/
作者
TengJinCheng
发布于
2026-03-10
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
TengJinCheng
Hello, I'm Teng.
公告
欢迎来到TengJinCheng工作铺!
音乐
封面

音乐

暂未播放

0:000:00
暂无歌词
分类
标签
站点统计
文章
157
分类
7
标签
114
总字数
109,939
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.4
文章许可
CC BY-NC-SA 4.0

文章目录