http://poj.org/problem?id=3522 //题目大意:求一棵生成树让最大边最小边差值最小 //题目类型:最小生成树+枚举 //解题思路:分析可知生成树一定是最小生成树,利用Kruskal算法枚举所有的最小生成树 #include <iostream> #include <algorithm> //#include <conio.h> using namespace std; #define narray 101 #define marray 5000 const int INF = 0x7fffffff; typedef struct edge { int a; int b; int w; }edge; edge edges[marray]; int final[narray]; int cnt[narray]; int n,m; bool cmp(const edge a,const edge b) { return a.w<b.w; } int findp(int n) { if(final[n]==n) return n; else final[n]=findp(final[n]); return final[n]; } bool Union(int a,int b) { int roota = findp(a); int rootb = findp(b); if(roota!=rootb) { if(cnt[a]>=cnt[b]) { final[rootb] = roota; cnt[roota]+=cnt[rootb]; } else { final[roota] = rootb; cnt[rootb]+=cnt[roota]; } return true; } else return false; } int main() { // freopen("in.txt","r",stdin); int a,b,w; int i,j; int num; int minslim; int firstw,lastw; while(scanf("%d%d",&n,&m)!=-1) { if(n==0 && m==0) break; minslim = INF; for(i=1;i<=m;++i) { scanf("%d%d%d",&edges[i].a,&edges[i].b,&edges[i].w); } sort(edges+1,edges+m+1,cmp); bool flag = false; if(n==2 && m==1) //注意考虑只有两个顶点一条边的情况 { printf("0/n"); continue; } for(j=1;j<=m;++j) //枚举 { num = 0; for(i=1;i<=n;++i) { final[i] = i; cnt[i] = 1; } for(i=j;i<=m;++i) { if(j+n-2>m) //剪枝 { flag = true; break; } a = edges[i].a; b = edges[i].b; w = edges[i].w; if(Union(a,b)) { num++; if(num==1) firstw = w; else if(num==n-1) { lastw = w; if(lastw-firstw<minslim) minslim = lastw-firstw; break; } } } if(flag) break; } if(minslim == INF) printf("-1/n"); else printf("%d/n",minslim); } //getch(); return 0; }