UVALive-3887 Slim Span (kruskal)

题目大意:定义无向图生成树的最大边与最小边的差为苗条度,找出苗条度最小的生成树的苗条度。

题目分析:先将所有边按权值从小到大排序,在连续区间[L,R]中的边如果能构成一棵生成树,那么这棵树一定有最小的苗条度。枚举所有这样的区间。

代码如下:

# include<iostream>
# include<cstdio>
# include<set>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const int N=105;
const int INF=1<<30;
struct Edge
{
    int u,v,w;
    bool operator < (const Edge &a) const {
        return w<a.w;
    }
};
Edge e[5005];
int fa[N],n,m;

int findFa(int u)
{
    if(fa[u]!=u)
        return fa[u]=findFa(fa[u]);
    return u;
}

bool judge()
{
    int cnt=0;
    REP(i,1,n+1) if(fa[i]==i) ++cnt;
    return cnt==1;
}

int main()
{
    //freopen("UVALive-3887 Slim Span.txt","r",stdin);
    while(scanf("%d%d",&n,&m)&&(n+m))
    {
        REP(i,0,m) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e,e+m);
        int ans=INF;
        REP(L,0,m){
            REP(i,1,n+1) fa[i]=i;
            REP(R,L,m){
                int u=e[R].u,v=e[R].v;
                int a=findFa(u);
                int b=findFa(v);
                if(a!=b)
                    fa[a]=b;
                if(judge()){
                    ans=min(ans,e[R].w-e[L].w);
                    break;
                }
            }
        }
        if(ans==INF)
            printf("-1
");
        else
            printf("%d
",ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/4927478.html