POJ 3522 生成树(kruskal)

这道题也是今天模拟赛的一道题,竟在poj上找到了,虽然有一丝差别。
题意:给一个图,求所有生成树中,最大边和最小边差值的最小值。
多组输入,可能会有不连通的情况,就是一丝差别。。。

/*
感觉自己也是NC,最开始的做法竟然是二分,判定答案mid是否可行的方法就是以beg为第一条边(最小或最大皆可,这篇博客里是以最小为例,就是说kruskal跑的是最小生成树),(1<=beg<=m-n+2)生成所有的最小生成树,一旦有边长与beg长的差超过mid就停止,函数返回0,如果循环了一遍beg发现找不到一棵生成树,那么mid就偏小了。

后来在poj上交这道题,稍微改那“一丝差别”时,才发现,自己这不是多搞出来一个二分的复杂度么。188ms与94ms的区别。
*/

解题思路:只需要一遍循环1<=beg<=m-n+2,求出所有生成树,对它们最大边全与最小边权的差取min就是答案了。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int n, m, f[101];

struct edge{
    int a, b, v;
    bool operator < (edge i) const{
        return v < i.v;
    }
}e[5001];

int find(int x){
    return f[x] = f[x] == x ? x : find(f[x]);
}

int kruskal(int beg){
    int ed = 0, res;
    for(int i = beg; i <= m && ed < n-1; i++){
        int fa = find(e[i].a), fb = find(e[i].b);
        if(fa != fb) f[fa] = fb, ed++, res = e[i].v - e[beg].v;
    }
    return ed == n-1 ? res : (1<<30);
}

int main()
{
    while(scanf("%d %d", &n, &m) && n){
        for(int i = 1; i <= n; i++) f[i] = i;
        int cot = 1;
        for(int i = 1; i <= m; i++){
            scanf("%d %d %d", &e[i].a, &e[i].b, &e[i].v);
            int fa = find(e[i].a), fb = find(e[i].b);   
            if(fa != fb) f[fa] = fb, cot++;
        }
        if(cot < n){
            printf("-1\n"); continue;
        }
        sort(e+1, e+m+1);

        int ans = (1<<30);
        for(int beg = 1; beg <= m-n+2; beg++){
            for(int i = 1; i <= n; i++) f[i] = i;
            ans = min(ans, kruskal(beg));
        }   
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值