P1546 [USACO3.1] 最短网络 Agri-Net

GESP8 冲刺课堂页:先建模,再压缩状态,最后读代码。

一、先回答问题

结论

输入是小规模邻接矩阵,用 Prim 每次把最便宜接入当前树的点加入。

容易误入的路

把 minEdge 理解成从 1 到某点的最短路,这是 MST 不是最短路。

二、核心观察

建模与压缩

minEdge[v] 表示 v 接入当前生成树的最低代价。

为什么不丢答案:每一步选择树外最小接入边,割性质保证不会错过最优生成树。

当前树 minEdge 答案

三、互动演示

步骤1
关键状态 A-
关键状态 B-
答案/目标-
复杂度看表
课堂动作手推

四、自己选答案

问题 1

Prim 的 minEdge 是什么?

问题 2

为什么 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;
}