(补题)苗条的树(poj_3522)
好多题没写啊~
---------------------------------
题意:给出一个由V个点和E条边组成的图G,每条边上有一个权值,要求构造出一棵生成树,使得树上的最大权值与最小权值的差尽可能小
做法:说到贪心就是Kruskal啦,从最小的边开始构造最小生成树,记下结果,取最小的那个。
实现并不难。
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; int ans; struct edge{ int u, v, w; edge() {} edge(int _u, int _v, int _w):u(_u), v(_v), w(_w) {} }; int cmp(edge a,edge b){return a.w<b.w;} vector<edge> e; int n,m,fa[105]; int findset(int x){ return fa[x]!=x?fa[x]=findset(fa[x]):x;} void Kruskal(int x){ int l=e[x].w,r,num=0; for(int i=1;i<=n;i++) fa[i]=i; for(int i=x;i<e.size();i++){ int u=e[i].u,v=e[i].v,w=e[i].w; u=findset(u),v=findset(v); if(u!=v){ fa[u]=v; num++; } if(num==n-1) { r=w; if(ans>r-l) ans=r-l; return ; } } } int main() { while(scanf("%d%d",&n,&m)!=EOF){ if(n==0&&m==0) break; e.clear(); ans=151515; for(int i=0;i<m;i++) { int v,w,c; scanf("%d%d%d",&v,&w,&c); e.push_back(edge(v,w,c)); } sort(e.begin(),e.end(),cmp); if (m<n-1){ printf("-1\n"); continue; } int ss; for(int i=0;i<=m-n+1;i++){ Kruskal(i); if(ans==0)break; } if(ans!=151515) printf("%d\n",ans); else printf("-1\n"); } return 0; }