#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=100; //顶点数
int father[MAXN];
int height[MAXN];
struct Edge{ //边的结构体
int from;
int to;
int length;
bool operator < (const Edge &e)const{
return length<e.length;
}
}edge[MAXN*MAXN];
void Inital(int n){ //并查集初始化
for(int i=0;i<=n;++i){
father[i]=i;
height[i]=0;
}
}
int Find(int x){
if(x!=father[x]) father[x]=Find(father[x]); //递归查询所属集合,并把查询途中的x的father都设为最顶层的根节点
return father[x];
}
void Union(int x,int y){
x=Find(x);
y=Find(y);
if(x!=y){
if(height[x]<height[y]){
father[x]=y;
}else if(height[y]<height[x]){
father[y]=x;
}else{
father[y]=x;
}
}
return ;
}
int Kruskal(int n,int EdgeNumber){ //kruskal算法
Inital(n);
sort(edge,edge+EdgeNumber); //算法时间复杂度O(ElogE)主要来源把边进行排序
int sum=0;
for(int i=0;i<EdgeNumber;++i){
Edge current=edge[i];
if(Find(current.from)!=Find(current.to)){ //这条边的起点和终点不属于同一个集合
Union(current.from,current.to);
sum+=current.length;
}
}
return sum;
}
int main() {
int n;
while (scanf("%d",&n)!=EOF){
if(n==0) break;
int edgenumber=n*(n-1)/2;
for(int i=0;i<edgenumber;++i){
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].length);
}
int answer=Kruskal(n,edgenumber);
printf("%d\n",answer);
}
return 0;
}
测试用例:
input:
3
1 2 1
1 3 2
2 3 4
output:
3
input:
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
output:
5