UVA1395 Slim Span(kruskal)

题目:Slim Span UVA 1395

题意:给出一副无向有权图,求生成树中最小的苗条度(最大权值减最小权值),如果不能生成树,就输出-1;

思路:将所有的边按权值有小到大排序,然后枚举每一条边,以这条边开始利用Kruskal算法生成树,生成过程中求出权值的最大值,这个最大值减去当前枚举的边的权值就是苗条度,再动态维护一下最小苗条度就可以了。

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <cmath>
#define INF 0x3f3f3f3f
#define mod 1000000007;
#define FRE() freopen("in.txt","r",stdin)
using namespace std;
const int maxn = 5005;
struct edge
{
    int st,en;
    int w;
}e[maxn];
int pre[maxn];
int n,m;

bool cmd(edge &a,edge &b)
{
    return a.w < b.w;
}

int _Find(int x)
{
    return x == pre[x] ? x : pre[x] = _Find(pre[x]);
}

int main()
{
    //FRE();
    while(scanf("%d%d",&n,&m) && n+m)
    {
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d",&e[i].st,&e[i].en,&e[i].w);
        }
        sort(e, e+m, cmd);
        int ans = INF;
        for(int i = 0; i < m; i++)//从小到大枚举每一条边,之后用求得的最大值减去这条边的权值
        {
            for(int i = 1; i <= n; i++) pre[i] = i;
            int cnt = n,mmax = -1;
            for(int j = i; j < m; j++)
            {
                int x = _Find(e[j].st),y = _Find(e[j].en);
                if(x != y)
                {
                    pre[y] = x;
                    cnt--;
                    mmax = max(mmax, e[j].w);//求出最小生成树中最大的权值
                }
            }
            if(cnt == 1)//因为是树,所以有n-1条边,当是一棵树的时候,就动态维护一下最小值
                ans = min(ans, mmax - e[i].w);
        }
        if(ans == INF)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2018-10-02 19:17  sykline  阅读(110)  评论(0编辑  收藏  举报