题意:
让你在一个无向图中找到一棵树,使得树中最大边和最小边之差最小。
思路:如果我们知道最小边是谁的话,那么最小的最大边一定是最小生成树中的最大边了。那么不难想到我们可以枚举最小边,然后构造最小生成树,然后用最大边减去最小边更新答案。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
using namespace std;
const int MAXN = 100+5;
const double eps = 1e-5;
const double inf = 1e9;
int n,m;
struct edge
{
int u,v,w;
bool operator < (const edge &a)const
{
return w < a.w;
}
} edge[MAXN*MAXN];
int pre[MAXN];
int findx(int x)
{
return pre[x] == x?x:pre[x] = findx(pre[x]);
}
int ans;
void kruskal()
{
ans = inf;
//枚举最小边i
for(int i = 0; i < m; ++i)
{
for(int j = 1; j <= n; ++j)pre[j] = j;
pre[findx(edge[i].v)] = findx(edge[i].u);
int cnt = 1;
if(cnt == n-1)
{
puts("0");
return;
}
//构造最小生成树
bool flag = 0;
for(int j = i+1; j < m; ++j)
{
int u = edge[j].u;
int v = edge[j].v;
int w = edge[j].w;
u = findx(u),v = findx(v);
if(u != v)
{
pre[v] = u;
cnt++;
if(cnt == n-1)
{
ans = min(ans,w - edge[i].w);
flag = 1;
break;
}
}
}
if(!flag)break;
}
if(ans == inf)puts("-1");
else printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n)
{
for(int i = 0; i < m; ++i)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge,edge+m);
kruskal();
}
return 0;
}