Uva1395.Slim Span(最小生成树变形)

Description

给出n个点 (n100) ,m条边,求出最大边减最小边差值最小的生成树

Solution

首先可以注意到n不是很大,最大只有100,自然而然想到的就是暴力的做法。

将边按权值从小到大排序。在排好序的边中枚举[L,R]区间内的边,判断是否能形成最小生成树,若可以,则当前的差值就为 e[R].we[L].w

可以注意到,对于枚举R的范围内,已经是最优的,因为当R继续增大时,对应权值也会增大,此时结果不会最优。所以可以跳出循环。但是并不意味着是全局最优的,因此还需要继续枚举L。

Code

#include<bits/stdc++.h>
#define ll long long
#define nmax 10000+5
#define nume 105
using namespace std;
struct edg{
    int f,t,w;
}e[nmax];
int fa[nume];
int n,m,ans = 100000000;
void makeset(int x){
    fa[x] = x;
}
int findset(int x){
    int rt = x, temp;
    while(fa[rt] != rt) rt=fa[rt];
    while(x!=rt){
        temp = fa[x];
        fa[x] = rt;
        x = temp;
    }
    return rt;
}
int unionset(int x ,int y){
    x = findset(x);
    y = findset(y);
    if(x == y) return -1;
    else{
        fa[x] = y;
        return 0;
    }
}
bool cmp(edg a, edg b){
    if(a.w<b.w) return true;
    else if(a.w == b.w){
        return a.f < b.f;
    }else return false;
}
void kur(){
    int num = n;
    int sta = 0,ed = 0;
    for(int i = 0;i<m;++i){
        for(int j = i;j<m;++j){
            num = n;
            sta = e[i].w,ed=e[j].w;
            for(int k = i;k<=j;++k){
                if(unionset(e[k].f,e[k].t)!=-1){
                    num--;
                }
            }
            for(int i = 1;i<=n;++i) makeset(i);
            if(num == 1){
                ans = min(ed - sta,ans);
                break;
            }
        }
    }
}
int main(){
    while(scanf("%d %d",&n,&m) != EOF){
        if(n == 0 && m == 0) break;
        ans = 100000000;
        for(int i = 1;i<=n;++i) makeset(i);
        for(int i = 0;i<m;++i){
            scanf("%d %d %d",&e[i].f,&e[i].t,&e[i].w);
        }
        sort(e,e+m,cmp);
        kur();
        if(ans == 100000000) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值