题意:给出一个n(<=100)个节点的图,求苗条度(最大边-最小边的值)最小的生成树。
solution:枚举+Kruskal
#include <vector>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define Inf 0x7fffffff
const int N = 105;
const int M = 5e3 + 7;
struct Edge{
int u, v, w;
Edge(int u, int v, int w):u(u),v(v),w(w){}
};
vector<Edge> E;
int r[M], pa[N];
bool cmp(int x, int y){
return E[x].w<E[y].w;
}
int find(int x){
return pa[x]==x?x:pa[x]=find(pa[x]);
}
int Kruskal(int n, int L, int R){
for ( int i=1; i<=n; i++ ) pa[i]=i;
for ( int i=L; i<=R; i++ ){
int id=r[i], u=E[id].u, v=E[id].v, w=E[id].w;
int pu=find(u), pv=find(v);
if( pu!=pv ) {
pa[pu]=pv;
}
}
for ( int i=2; i<=n; i++ )
if( find(i-1)!=find(i) ) return -1;
return E[r[R]].w-E[r[L]].w;
}
inline int read(){
int x=0, f=1; char ch=getchar();
while( !isdigit(ch) ) { if( ch=='-' ) f=-1; ch=getchar(); }
while( isdigit(ch) ) { x=x*10+ch-'0'; ch=getchar(); }
return x*f;
}
int main(){
int n, m;
while( scanf("%d%d", &n, &m )==2 && n ){
memset(r,0,sizeof(r));
memset(pa,0,sizeof(pa));
E.clear();
for ( int i=0; i<m; i++ ){
int u, v, w;
u=read(), v=read(), w=read();
E.push_back(Edge(u,v,w));
}
for ( int i=0; i<=m-1; i++ ) r[i]=i;
sort(r,r+m,cmp);
int l=0, r=n-1;
int ret=Inf, ans;
for ( int l=0; l<=m-1; l++ ){
for ( int r=l; r<=m-1; r++ ){
ans=Kruskal(n,l,r);
if( ans!=-1 ) {
ret=min(ret, ans);
break;
}
}
}
printf("%d\n", ret==Inf?-1:ret );
}
}