P1195 口袋的天空

点击查看代码
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1005, M = 10005;

struct Edge {
    int u, v, w;
    bool operator<(const Edge& o) const { return w < o.w; }
} e[M];

int n, m, k, p[N];

// 极简并查集
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }

int main() {
    // I/O 优化
    ios::sync_with_stdio(0); cin.tie(0);

    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        cin >> e[i].u >> e[i].v >> e[i].w;
    }

    // 1. 边排序,Kruskal 的贪心精髓
    sort(e, e + m);
    
    // 2. 初始化并查集
    for (int i = 1; i <= n; i++) p[i] = i;

    int res = 0, cnt = 0;
    
    // 3. 跑最小生成森林
    for (int i = 0; i < m; i++) {
        // 核心变型:当连够了 n - k 条边时,图中恰好剩下 k 个连通块(k 棵树)
        if (cnt == n - k) break;
        
        int u = find(e[i].u), v = find(e[i].v);
        if (u != v) {
            p[u] = v;
            res += e[i].w;
            cnt++;
        }
    }

    // 4. 判定是否有解
    // 如果所有的边都用完了,成功连上的边数还是不到 n - k,说明凑不出 k 个连通块
    if (cnt == n - k) {
        cout << res << "\n";
    } else {
        cout << "No Answer\n";
    }

    return 0;
}
posted @ 2026-03-20 21:01  AnoSky  阅读(5)  评论(0)    收藏  举报