基于稠密完全图邻接矩阵的 Prim 算法求最小生成树
OJ: roj
题目 ID: 2040
难度:普及-
标签:图论最小生成树
创建: 2026-10-01 04:29
更新: 2026-10-06 10:10
题目描述
约翰有
思路
这是一道稠密图最小生成树模板题。
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-04-18 10:00
# update_at: 2026-04-18 10:00
import sys
INF = 10**18
def prim_mst(n: int, adj: list[list[int]]) -> int:
"""计算稠密图的最小生成树边权和。"""
min_cost = [INF] * n
min_cost[0] = 0
visited = [False] * n
for _ in range(n):
# 挑选当前未加入树且到树距离最小的农场
u = min((v for v in range(n) if not visited[v]), key=lambda v: min_cost[v])
visited[u] = True
for v in range(n):
if not visited[v] and adj[u][v] < min_cost[v]:
min_cost[v] = adj[u][v]
return sum(min_cost)
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n = next(data)
adj = [[next(data) for _ in range(n)] for _ in range(n)]
print(prim_mst(n, adj))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 10:09
* update_at: 2026-10-06 10:09
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 105;
const ll INF = (ll)1e18;
ll adj[MAXN][MAXN]; // 邻接矩阵,adj[i][j] 表示农场 i 到农场 j 的距离
ll min_cost[MAXN]; // 未加入树的农场到当前树的最小边权
bool in_tree[MAXN]; // 标记农场是否已加入最小生成树
// 在稠密完全图上用 O(n^2) Prim 算法求最小生成树边权和
ll prim_mst(int n) {
for (int i = 1; i <= n; ++i) {
min_cost[i] = INF;
in_tree[i] = false;
}
min_cost[1] = 0; // 从农场 1 开始构建生成树
ll total = 0;
for (int round = 1; round <= n; ++round) {
// 在未加入树的农场中选出到树距离最小的点 u
int u = -1;
for (int i = 1; i <= n; ++i) {
if (!in_tree[i] && (u == -1 || min_cost[i] < min_cost[u])) {
u = i;
}
}
in_tree[u] = true;
total += min_cost[u];
// 用 u 到其它未加入树农场的边松弛最小距离
for (int v = 1; v <= n; ++v) {
if (!in_tree[v] && adj[u][v] < min_cost[v]) {
min_cost[v] = adj[u][v];
}
}
}
return total;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> adj[i][j];
}
}
cout << prim_mst(n) << "\n";
return 0;
}