题意很简单:求一颗生成树使最大边和最小边的差最小。
根据最小生成树的性质我们可以知道,最大边一定是最小的,否则会有更小的边来替换。不过如何使得最小边最大呢。我采用的方法是枚举,枚举每一个能构成最小生成树的情况(一定是能构成最小生成树的,我在这坑了好长时间)。计算最大值和最小值的差值更新答案就好啦。
下附AC代码。
#include<iostream>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#define maxn 10005
using namespace std;
int q,m,n;
int u[maxn],e[maxn],temp[maxn],fa[maxn],w[maxn],vis[maxn];
int cmp(int i,int j)
{
return w[i]<w[j];
}
int find(int x)
{
return fa[x]==x? x : fa[x]=find(fa[x]);
}
int kruskal()
{
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
temp[i]=i;
sort(temp+1,temp+m+1,cmp);
int ans=987654321;
for(int start=1;start<=m;start++)
{
int now=987654321;
int cnt=0;
for(int j=1;j<=n;j++)
fa[j]=j;
for(int i=start;i<=m;i++)
{
int t=temp[i];
int x=find(u[t]);
int y=find(e[t]);
if(x==y) continue;
fa[x]=y;
cnt++;
if(cnt==n-1)
{
int now1=temp[i];
int now2=temp[start];
now=w[now1]-w[now2];
break;
}
}
ans=min(ans,now);
}
if(ans<987654321)
return ans;
else
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&m) && (n||m))
{
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
u[i]=a;
e[i]=b;
w[i]=c;
}
cout<<kruskal()<<endl;
}
}