题目链接: 传送门
给出一个n(2 <= n <= 100)个结点的无向图,找一颗苗条度(最大边减最小边)最小的生成树。图中不包含自环和重边。
解题思路:
枚举树上的最小边,从这条最小边开始构建MST,此时这棵树是以该边为最小边的苗条度最小的生成树。因为构建MST时会使最大边最小。
代码:
#include <iostream>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long llt;
const int N = 110;
const int M = 510;
const int INF = 0x3fffffff;
const int mod = 10000;
struct Edge{
int u,v,w;
bool operator < (const Edge&a) const{
return a.w > w;
}
}edge[N*N];
int parent[N];
int n,m;
void init()
{
for(int i = 0; i < N; ++i) parent[i] = i;
}
int find(int a)
{
while(a != parent[a]){
parent[a] = parent[parent[a]];
a = parent[a];
}
return a;
}
void merge(int a,int b)
{
int i = find(a);
int j = find(b);
if(i != j) parent[i] = j;
}
int kruskal(int k)
{
int cnt = 0;
for(int i = k; i < m; ++i){
int u = edge[i].u;
int v = edge[i].v;
if(find(u) != find(v)){
cnt++;
merge(u,v);
}
if(cnt == n-1){
return edge[i].w;
}
}
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
if(n == 0 && m == 0) break;
for(int i = 0; i < m; ++i){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge,edge+m);
init();
int ans = kruskal(0);
if(ans == -1){
printf("-1\n"); continue;
}
ans -= edge[0].w;
for(int i = 1; i <= m-n+1; ++i){
init();
int r = kruskal(i);
if(r == -1) continue;
ans = min(ans,r-edge[i].w);
}
printf("%d\n",ans);
}
// system("PAUSE");
return 0;
}