kruskal:
将图中的边按边权排好升序,然后从小的开始遍历,如果这条边的起点终点在一个联通图(并查集)里就不加入这条边,反之加入边,并且两个点加到一个并查集里。
#include<cstdio>
#include<algorithm>
#define MAX_N 111
using namespace std;
int N, M;
struct edge {
int from, to;
int cost;
}E[MAX_N*MAX_N];
int father[MAX_N];
bool cmp(edge a, edge b)
{
return a.cost < b.cost;
}
void init() {
for (int i = 1;i < MAX_N;i++)
father[i] = i;
}
int fid(int x)
{
if (x == father[x])
return x;
return father[x] = fid(father[x]);
}
bool same(int x, int y)
{
return fid(x) == fid(y);
}
void unionset(int x, int y)
{
int u = fid(x), v = fid(y);
if (u == v)
return;
father[u] = v;
}
long long kruskal()
{
long long res=0;
sort(E + 1,E + 1 + M, cmp);
for (int i = 1;i <= M;i++)
{
if (same(E[i].from, E[i].to))
continue;
unionset(E[i].from, E[i].to);
res += E[i].cost;
}
return res;
}
int main()
{
while (scanf("%d%d", &M, &N) == 2)
{
if (M == 0) break;
init();
for (int i = 1;i <= M;i++)
scanf("%d%d%lld", &E[i].from, &E[i].to, &E[i].cost);
int res = kruskal();
for (int i = 1;i <= N;i++)
if (!same(i, 1))
res = -1;
if (res == -1)
printf("?\n");
else
printf("%lld\n", res);
}
return 0;
}