您的位置:首页 > 其它

UVa--1395 Slim Span(生成树)

2016-02-22 22:08 357 查看

题意

给定带权无向图 G,定义:

The slimness of a spanning tree T is defined as the difference between the largest weight and the smallest weight among the n−1 edges of T.

求 slimness 尽可能小的生成树。

题解

把边按权值从小到大排序,枚举每一个边的区间,因为对于一个连续的边集区间[L,R],如果这些边能够使图连通,则一定存在slimness最大为 W[R]−W[L] 的生成树。

从 0…m 枚举 L,对每一个 L,从 L…m 枚举 R,同时用并查集判断此时图是否连通,如果连通,更新最小值,换下一个 L 继续枚举。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100 + 5;
const int maxe = 5000;
const int inf  = 1 << 30;
int  p[maxn];
int  u[maxe], v[maxe], w[maxe], r[maxe];
int  n, m;

int  find(int x) { return x == p[x] ? x : p[x] = find(p[x]); }
int  cmp(int i, int j) { return w[i] < w[j]; }
void initUFS() { for(int i = 1; i <= n; ++i) p[i] = i; }

void solve()
{
int ans = inf;
for(int i = 0; i < m; ++i)
{
initUFS();
int cnt = n;
for(int j = i; j < m; ++j)
{
int R = r[j];                   //第j条边在排序前的下标
int x = find(u[R]), y = find(v[R]);
if(x != y)
{
p[x] = y;
if(--cnt == 1){             //连通
ans = min(ans, w[R] - w[r[i]]);
break;
}
}
}
}
if(ans == inf) ans = -1;
cout << ans << endl;
}

int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif // LOCAL
ios::sync_with_stdio(false);
while(cin >> n >> m && n)
{
for(int i = 0; i < m; ++i)
{
r[i] = i;                       //初始化边序号
cin >> u[i] >> v[i] >> w[i];
}
sort(r, r + m, cmp);
solve();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UVa 生成树 Kruskal middle