输入是小规模邻接矩阵,用 Prim 每次把最便宜接入当前树的点加入。
P1546 [USACO3.1] 最短网络 Agri-Net
GESP8 冲刺课堂页:先建模,再压缩状态,最后读代码。
一、先回答问题
把 minEdge 理解成从 1 到某点的最短路,这是 MST 不是最短路。
二、核心观察
minEdge[v] 表示 v 接入当前生成树的最低代价。
为什么不丢答案:每一步选择树外最小接入边,割性质保证不会错过最优生成树。
当前树
minEdge
答案
三、互动演示
步骤1
关键状态 A-
关键状态 B-
答案/目标-
复杂度看表
课堂动作手推
点击下一步开始。
四、自己选答案
Prim 的 minEdge 是什么?
先判断,再点按钮。
为什么 O(n^2) 可以?
先判断,再点按钮。
五、手推结果
| 数组 | 含义 |
|---|---|
| used | 是否进树 |
| minEdge | 最小接入代价 |
| ans | 已选边权和 |
课堂要求:每题先说清对象、关系、保留的信息、压缩掉的信息,再写代码。
六、C++14 参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
const int INF = 1e9;
int w[N][N];
int minEdge[N];
bool used[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> w[i][j];
}
}
for (int i = 1; i <= n; i++) minEdge[i] = INF;
minEdge[1] = 0;
int ans = 0;
for (int step = 1; step <= n; step++) {
int u = -1;
for (int i = 1; i <= n; i++) {
if (!used[i] && (u == -1 || minEdge[i] < minEdge[u])) {
u = i;
}
}
used[u] = true;
ans += minEdge[u];
for (int v = 1; v <= n; v++) {
if (!used[v] && w[u][v] < minEdge[v]) {
minEdge[v] = w[u][v];
}
}
}
cout << ans << '\n';
return 0;
}