点击查看代码
#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;
}