kruskal和prim算法都有额外的东西要写,prim需要写队列容器,kruskal需要写并查集,不过kruskal易于理解,并且kruskal的对象是边,本次采用kruskal算法解决该题
题目是给N个村庄和每个村庄间的距离,求其中的最小生活树
注意要处理好村庄和边的数目之间的关系
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int V_MAX = 105;
const int M_MAX = 5000;
int N,M;//村庄数目
typedef struct edge
{
int from, to, cost;
}edge;
edge edg[M_MAX];
int par[V_MAX];
int height[V_MAX];
void init(int n)
{
for(int i=1; i<=n; i++){par[i] = i;height[i] = 0;}
}
int find(int x)
{
if(par[x] == x){return x;}
else
return par[x] = find(par[x]);
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if(x == y)return;
if(height[x]> height[y])
par[y] = x;
else
{
par[x] = y;
if(height[x] == height[y])
height[y]++;
}
}
bool same(int x, int y)
{
return find(x) == find(y);
}
bool cmp(const edge & a, const edge &b)
{
return a.cost < b.cost;
}
int solve()
{
int sum = 0;
sort(edg,edg+M,cmp);
for(int i=0; i<M; i++)
{
edge e = edg[i];
if(!same(e.from, e.to)){
unite(e.from,e.to);
sum += e.cost;
}
}
return sum;
}
int main()
{
while(scanf("%d",&N)!=EOF)
{
edge e;
if(N == 0)break;
init(N);
memset(edg, 0, sizeof(edg));
M = N*(N-1) / 2; //因为N比较小,所以不会越界
for(int i=0; i<M; i++)
{
scanf("%d%d%d",&edg[i].from, &edg[i].to, &edg[i].cost);
}
cout << solve() <<endl;
}
return 0;
}