Description
n个点m条边的无向带权图,求最小生成树
Input
多组用例,每组用例第一行为两个整数n和m分别表示点数和边数,之后m行每行三个整数a,b,c表示a和b之间有一条权值为c的边,以0 0结束输入(2<=n<=100,0<=m<=n*(n-1)/2)
Output
对于每组用例,输出最小生成树权值和,如果最小生成树不存在则输出-1
Sample Input
4 5
1 2 3
1 3 5
1 4 6
2 4 6
3 4 7
4 6
1 2 10
1 3 100
1 4 90
2 3 20
2 4 80
3 4 40
2 1
1 2 1
3 0
3 1
1 2 1
3 3
1 2 2
2 3 5
1 3 6
5 10
1 2 110
1 3 120
1 4 130
1 5 120
2 3 110
2 4 120
2 5 130
3 4 120
3 5 110
4 5 120
5 10
1 2 9384
1 3 887
1 4 2778
1 5 6916
2 3 7794
2 4 8336
2 5 5387
3 4 493
3 5 6650
4 5 1422
5 8
1 2 1
2 3 100
3 4 100
4 5 100
1 5 50
2 5 50
3 5 50
4 1 150
0 0
Sample Output
1
20
0
-1
-1
1
0
1686
50
Solution
最小生成树裸题
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 222
#define maxm 55555
#define INF 0x3f3f3f3f
struct node
{
int u,v,w;
}edge[maxm];
int n,m,fa[maxn];
int cmp(node a,node b)
{
if(a.w!=b.w)return a.w<b.w;
if(a.u!=b.u)return a.u<b.u;
return a.v<b.v;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int kruskal(int n,int m)
{
int ans=INF;
sort(edge,edge+m,cmp);
for(int i=0;i<=m-n+1;i++)
{
int temp=-1,cnt=0;
for(int j=1;j<=n;j++)fa[j]=j;
for(int j=i;j<m;j++)
{
int x=find(edge[j].u),y=find(edge[j].v);
if(x!=y)
{
cnt++;
fa[x]=y;
if(cnt==n-1)
{
temp=edge[j].w-edge[i].w;
break;
}
}
}
if(temp!=-1)ans=min(ans,temp);
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m),n||m)
{
for(int i=0;i<m;i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
int ans=kruskal(n,m);
if(ans==INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}