想看更多的解题报告:
http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:有N个节点,M条无向边的一个图,求在这个图中所有的生成树中,权值最大边减去权值最小边的最小值,如果不能构成一颗生成树没有就输出-1
解题思路:由于N与M都不大,所以对M条边排序后枚举边的起始点,kruscal后看能不能构成一颗生成树,可以的话判断最大边-最小边
/* Memory 232K Time 94MS */ #include <iostream> using namespace std; #define MAXM 5000 #define MAXV 105 #define inf 1<<29 typedef struct{ int s,t,w; }Edge; Edge edge[MAXM]; int n,m,ans,set[MAXV]; int find(int x){ if(x==set[x]) return x; else{ int rt=find(set[x]); set[x]=rt; return set[x]; } } bool TUnion(int a,int b){ int fa=find(a); int fb=find(b); if(fa==fb) return false; set[fb]=fa; return true; } void kruskal(int start){ int i,min=inf,max=-1,s,t,w,cnt=0; for(i=0;i<=n;i++) set[i]=i; for(i=start;i<m;i++){ s=edge[i].s; t=edge[i].t; w=edge[i].w; if(TUnion(s,t)){ if(w<min) min=w; if(w>max) max=w; cnt++; if(cnt==n-1) break; } } if(cnt!=(n-1)) return ; if(ans>max-min) ans=max-min; } int cmp(const void *a,const void *b){ return (*(Edge *)a).w-(*(Edge *)b).w; } bool work(){ int i; ans=inf; kruskal(0); if(ans==inf) return false; for(i=1;i<m;i++) kruskal(i); return true; } int main(){ int i; while(scanf("%d%d",&n,&m) && (n || m)){ for(i=0;i<m;i++) scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].w); qsort(edge,m,sizeof(edge[0]),cmp); if(!work()) printf("-1\n"); else printf("%d\n",ans); } return 0; }