(补题)苗条的树(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;  
}  

 

posted @ 2017-08-30 14:08  臼邦庶民  阅读(279)  评论(0编辑  收藏  举报