UVa 1395

题意

求最苗条生成树(即最大边权值-最小边权值)最小的生成树, 若能构成最苗条生成树输出苗条度, 否则输出-1

思路

复健题目一个月没做题第一发就是AC
思路很简单的Kruskal算法求最小生成树
遍历枚举开始位置,当生成n-1条边时记录苗条度即可

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
int n, m;
const int maxn = 105;
const int maxm = 5000;
const int INF = 0x3f3f3f3f;
int f[maxn];
//typedef unsigned long long ULL;

void init(){
    for( int i = 0; i <= n; i++ )
        f[i] = i;
}

int _find(int a){
    if( f[a] == a ) return f[a];
    else return f[a] = _find(f[a]);
}

void _union(int a, int b){
    int aa = _find(a), bb = _find(b);
    if(aa != bb){
        f[bb] = aa;
    }
}

struct edge{
    int fr, to, cst;
}ed[maxm];

bool cmp(struct edge a, struct edge b){
    return a.cst < b.cst;
}

bool _same( int a, int b ){
    if( _find(a) != _find(b) )
        return false;
    return true;
}

int kruskal(){
    int e;
    int mmin = INF;
    for(int i = 0; i < m; ++i){
        e = 0;
        init();
        for(int j = i; j < m; j++){
            if( !_same(ed[j].fr, ed[j].to) ){
                e++;
                if(e == n-1)
                    mmin = min(mmin, ed[j].cst-ed[i].cst);
                _union(ed[j].fr, ed[j].to);
            }
        }
    }
    return mmin == INF ? -1 : mmin;
}

int main()
{
    int a, b, c;
    while( ~scanf("%d%d",&n, &m) && n ){
        init();
        memset(ed, 0, sizeof ed);
        for(int i = 0; i < m; i++){
            scanf("%d%d%d",&a, &b, &c);
            ed[i] = {a,b,c};
        }
        sort(ed, ed+m, cmp);
        printf("%d
", kruskal());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740537.html