【题意】
求一颗生成树,使得边权的最大值与最小值之差最小。
【题解】
可以二分答案,但是没必要,只要枚举最小边即可。
使用kruskal的贪心法,得到的生成树的最大边必定最小,所以最大边与最小边之差最小。
【代码】
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100;
const int maxe=maxn*(maxn-1)/2;
struct edge
{
int x,y,w;
}e[maxe];
int fa[maxn];
int n,m;
int find(int x)
{
if (fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
int kruskal(int st)
{
int i,x,y,num=n,ans=-1;
for (i=1;i<=n;i++)
fa[i]=i;
for (i=st;i<m;i++)
{
x=find(e[i].x);
y=find(e[i].y);
if (x==y) continue;
fa[x]=y;
num--;
if (num==1)
{
ans=e[i].w;
break;
}
}
return ans-e[st].w;
}
int cmp(edge a,edge b)
{
return a.w<b.w;
}
int main()
{
freopen("pin.txt","r",stdin);
freopen("pou.txt","w",stdout);
int ans,i,tt;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n==0 && m==0) break;
for (i=0;i<m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
sort(e,e+m,cmp);
ans=kruskal(0);
if (ans<0)
{
printf("%d\n",-1);
continue;
}
for (i=1;i<m;i++)
{
tt=kruskal(i);
if (tt<0) break;
if (tt<ans) ans=tt;
}
printf("%d\n",ans);
}
return 0;
}