直接用Kruskal算法求解,用cnt记录最小生成树的边数进行判断
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 110;
int par[maxn], ran[maxn];
void init(int m) {
for (int i = 0; i <= m; i++) {
par[i] = i, ran[i] = 0;
}
}
int seek(int x) {
if (par[x] == x) return x;
else return par[x] = seek(par[x]);
}
void unite(int x, int y) {
x = seek(x), y = seek(y);
if (x == y) return;
if (ran[x] == ran[y]) par[x] = y;
else {
par[y] = x;
if (ran[x] == ran[y]) ran[x]++;
}
}
struct Edge {
int u, v, cost;
bool operator < (const Edge &another) const {
return cost < another.cost;
}
}edge[maxn*maxn];
int main()
{
int m, n, u, v, cost;
while (scanf("%d %d", &n, &m) == 2 && n) {
for (int i = 1; i <= n; i++) {
scanf("%d %d %d", &u, &v, &cost);
edge[i].u = u, edge[i].v = v, edge[i].cost = cost;
}
sort(edge + 1, edge + 1 + n);
init(m);
int cnt = 0, ans = 0;
for (int i = 1; i <= n; i++) {
if (cnt == m - 1) break;
if (seek(edge[i].u) != seek(edge[i].v)) {
cnt++;
ans += edge[i].cost;
unite(edge[i].u, edge[i].v);
}
}
if (cnt == m - 1) printf("%d\n", ans);
else printf("?\n");
}
return 0;
}