题目链接:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105277#problem/B
题意:
给出一个n节点的图,边最多为n*(n-1)/2条边,求苗条度(最大边权值减最小边权值)尽量小的生成树。
分析:
按权值从小到大排序,从小到大枚举L,然后直到连通边数有n-1时,就枚举另一个L,保存最优值就可以了。
#include <stdio.h>
#include <algorithm>
#define INF 0x7fffffff
const int maxn = 105;
struct node
{
int x, y, v;
friend bool operator < ( node n1, node n2 )
{
return n1.v < n2.v; //权值排序
}
}a[maxn*maxn];
int fa[maxn];
void init ( int n )
{
for ( int i = 1; i <= n; i ++ )
fa[i] = i;
}
int find ( int x ) { return fa[x] == x ? x : fa[x] = find ( fa[x] ); }
inline int Min ( int a, int b ) { return a < b ? a : b; }
inline int Max ( int a, int b ) { return a > b ? a : b; }
int main ( )
{
int n, m;
while ( ~ scanf ( "%d%d", &n, &m ) && ( n || m ) )
{
for ( int i = 0; i < m; i ++ )
scanf ( "%d%d%d", &a[i].x, &a[i].y, &a[i].v );
std :: sort ( a, a+m );
int ans = INF;
for ( int i = 0; i < m; i ++ )
{
init ( n );
int cnt = 0, mn, mx, j;
mn = INF, mx = 0;
for ( j = i; j < m; j ++ )
{
int fx = find ( a[j].x ), fy = find ( a[j].y );
if ( fx != fy )
{
fa[fx] = fy;
cnt ++; //统计连通的边数
mn = Min ( mn, a[j].v );
mx = Max ( mx, a[j].v );
}
if ( cnt >= n-1 ) //n-1条证明生成树已完成
break ;
}
if ( j < m )
ans = Min ( ans, mx-mn ); //找最小值
}
printf ( "%d\n", ans == INF ? -1 : ans );
}
return 0;
}