題目鏈接:
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;
}