题意:求图的一个生成树使其最大边权与最小边权的差值最小,求其最小值
思路:利用贪心思想,先对边进行排序,然后从最小边开始枚举,每次进行kruskal向右加入边,若加入边刚好能遍历所有点,记录最后加入的边与第一个边的差值。最后得到最小值。
在kruskal枚举第一个边的时候没有加入判断是否剩下的边能够组成一个树,结果WA了几次,但是怎么觉得不加也没所谓呢。。?
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define MAXN 50050 #define inf 1000000000 using namespace std; int pre[108]; int n,m,temp;int l,r;int ans; struct Edge{ int x,y,len; }edge[MAXN]; int cmp(Edge a,Edge b) { return a.len<b.len; } int find(int x) { if(x!=pre[x]) pre[x]=find(pre[x]); return pre[x]; } void kruskal(int x) { int num; for(int i=1;i<=n;i++) pre[i]=i; l=edge[x].len;num=0; //cout<<l<<endl; for(int i=x;i<=temp;i++) { int a=find(edge[i].x); int b=find(edge[i].y); if(a!=b) { pre[a]=b; num++; } if(num==n-1) { r=edge[i].len; if(ans>r-l)ans=r-l; //cout<<ans<<endl; return ; } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; ans=20050; for(int i=0;i<m;i++) { int v,w,c; scanf("%d%d%d",&v,&w,&c); edge[i].x=v; edge[i].y=w; edge[i].len=c; temp=i; } sort(edge,edge+temp+1,cmp); //cout<<edge[0].len<<' '<<edge[temp].len<<endl; for(int i=0;i<=temp&&m-i>=n-1;i++) {kruskal(i);if(ans==0)break;} if(ans!=20050) printf("%d ",ans); else printf("-1 "); } return 0; }