求一棵最大边与最小边差值最小的生成树 一开始二分差值,跑了400多MS,后来看了别人的思路枚举最小边,只要100多MS #include<iostream> #include<algorithm> using namespace std; struct node { int u,v,w; }g[5005]; int parent[105],vn,en; void init(int n) { for(int i=1;i<=n;i++) parent[i]=i; } int cmp(const node &a,const node &b) { return a.w<b.w; } int find(int x) { while(parent[x]!=x) x=parent[x]; return x; } int kruskal(int l,int r) { int a,b,i,num=0; for(i=1;i<=en;i++) { if(g[i].w<l||g[i].w>r) continue; a=find(g[i].u); b=find(g[i].v); if(a!=b) { num++; parent[a]=b; } if(num==vn-1) return 1; } return 0; } int main() { int i,a,b,wei,mid,flag,ans; while(scanf("%d%d",&vn,&en)!=EOF) { if(vn==0&&en==0) break; for(i=1;i<=en;i++) scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w); sort(g+1,g+1+en,cmp); a=0; b=g[en].w-g[1].w; //cout<<b<<endl; g[0].w=ans=-1; while(a<=b) { mid=(a+b)/2; flag=0; for(i=1;i<=en;i++)//注意条件,一开始写成g[i].w+mid<=g[en].w,错了 //如果g[i].w+mid>g[en].w,也能有生成树,则mid可行, //否则可能会导致mid不可行,二分区间就错了 { if(g[i].w==g[i-1].w) continue; init(vn); if(kruskal(g[i].w,g[i].w+mid)) { flag=1; break; } } if(flag) { ans=mid; b=mid-1; } else a=mid+1; } printf("%d/n",ans); } return 0; } /* #include<iostream> #include<algorithm> using namespace std; struct node { int u,v,w; }g[5005]; int parent[105],vn,en; void init(int n) { for(int i=1;i<=n;i++) parent[i]=i; } int cmp(const node &a,const node &b) { return a.w<b.w; } int find(int x) { while(parent[x]!=x) x=parent[x]; return x; } int kruskal(int start) { int a,b,i,num=0; for(i=start;i<=en;i++) { a=find(g[i].u); b=find(g[i].v); if(a!=b) { num++; parent[a]=b; } if(num==vn-1) return i; } return 0; } int main() { int i,a,b,wei,mid,flag,ans; while(scanf("%d%d",&vn,&en)!=EOF) { if(vn==0&&en==0) break; for(i=1;i<=en;i++) scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w); sort(g+1,g+1+en,cmp); init(vn); a=kruskal(1); if(a) ans=g[a].w-g[1].w; else { puts("-1"); continue; } for(i=2;i<=en;i++) { init(vn); a=kruskal(i); if(a) ans=min(ans,g[a].w-g[i].w); } printf("%d/n",ans); } return 0; } */