#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string.h>
using namespace std;
#define N 1000
int f[N],vis[N];
struct node
{
int a ,b,w;
friend bool operator <(const node &A,const node &B)
{return A.w>B.w;}
};
node data[N];
int find(int a)
{
int i=a;
while(f[i]!=i)
i=f[i];
int j=a,k;
while(f[j]!=i)
{
k=f[j];
f[j]=i;
j=k;
}
return i;
}
void union1(int a ,int b)
{
int fa=f[a];
int fb=f[b];
if(fa!=fb)
f[fa]=fb;
}
void init(int n)
{for(int i=1;i<=n;i++) f[i]=i;}
int main()
{
int i,j,n,m,ans;
while(scanf("%d%d",&n,&m))
{
if(!n&&!m)break;
ans=0;
memset(vis,0,sizeof(vis));
init(n);
for(i=1;i<=m;i++)
scanf("%d%d%d",&data[i].a,&data[i].b,&data[i].w);
sort(data+1,data+1+m);
for(i=1;i<=m;i++)
{
int a=find(data[i].a);
int b=find(data[i].b);
if(a!=b)//一开始肯定都是不在一颗树上的,连起来
{
if(vis[a]&&vis[b])continue;
if(vis[a]||vis[b])vis[a]=vis[b]=1;
union1(a,b);//无论怎样都连起来
ans+=data[i].w;
}
else if(!vis[a])//在同一棵树上却都没有环,才可以将两点连起来
{
vis[a]=vis[b]=1;
union1(a,b);
ans+=data[i].w;
}//这里不用else,就是如果有环,丢掉
}
printf("%d\n",ans);
}
return 0;
}
/*
3 3
0 1 1
1 2 1
2 0 1
4 5
0 1 1
1 2 1
2 3 1
3 0 1
0 2 2
0 0
*/
这道题的做法和克鲁斯卡尔算法过程上差不多,都是利用了并查集的性质
合并的时候分三种情况:1是否两个都有环,2其中一个有环,3两个都没有环
有位朋友说:不能直接求最大生成树,有待验证!
判断树有没有环,用Vis数组,这个过程很典型!