【图论】[CQBZOJ1362] 苗条的生成树

题目描述:点击此处
解题思路:
构造最小生成树,并计算苗条度,然后不断删最短边,用kruskal构造最小生成树,计算苗条度,直至图不再连通,输出苗条度。
若一开始就不是一棵树,则输出-1;

因为kruskal是贪心的算法,所以确定了最小边之后,最大边也随之确定,且最大边最小。

实现代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXM 5000
#define INF 0x7fffffff
#define MAXN 100
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
int n,m,fa[MAXN+10],ans;
struct node{
    int u,v,wt;
    bool operator<(const node &x)const{
        return wt<x.wt;
    }
}edge[MAXM+10];
void read(){
    Read(n),Read(m);
    int i,u,v,wt;
    for(i=1;i<=m;i++){
        Read(u),Read(v),Read(wt);
        edge[i].u=u,edge[i].v=v,edge[i].wt=wt;
    }
    sort(edge+1,edge+m+1);
}
int find(int x){
    return fa[x]=(fa[x]!=x)?find(fa[x]):x;
}
int kruskal(int s){
    int maxe=INF+1,mine=INF,i,u,v,wt,cnt=1;
    for(i=1;i<=n;i++)
        fa[i]=i;
    for(i=s;i<=m;i++){
        u=edge[i].u,v=edge[i].v,wt=edge[i].wt;
        if(find(u)==find(v))
            continue;
        fa[fa[u]]=fa[v];
        maxe=max(wt,maxe);
        mine=min(wt,mine);
        cnt++;
        if(cnt==n)
            break;
    }
    if(cnt<n)
        return -1;
    return maxe-mine;
}
int main()
{
    while(1){
        ans=INF;
        read();
        if(!n)
            return 0;
        int i,t;
        for(i=1;i<=m;i++){
            t=kruskal(i);
            if(t==-1)
                break;
            if(t<ans)
                ans=t;
            if(!ans)
                break;
        }
        if(ans==INF)
            puts("-1");
        else
            printf("%d\n",ans);
    }
}
posted @ 2015-08-26 20:14  outer_form  阅读(234)  评论(0编辑  收藏  举报