苗条的生成树 Slim Span--洛谷

传送门

钢哥终于没给黑题紫题了(卑微v

稍稍需要多想一点点

--------------------------------------------------------------------------------------------------------

题意简述

求所有生成树中最大边权与最小边权差最小的,输出它们的差值。

输入:

输入文件包含多组测试数据,每组测试数据如下: 第1行:2个整数n m (2 ≤ n ≤ 100 and 0 ≤ m ≤ n(n − 1)/2),n表示顶点数,m表示边数。接下来m行,每行3个空格分开的整数a b w(1 ≤ w ≤ 10000) , 表示顶点a与顶点b之间有一条边,权值为w。

输出:

对每组测试数据,如果图存在生成树,输出生成树的差值最小的;否则,输出-1。

--------------------------------------------------------------------------------------------------------

由于n的值比较小

所以可以不用那种优化到极致的神仙算法/思路(可以小小的偷偷懒

把所有边按边权排序

从每个边求最小生成树

用最小生成树中的最大边权和最小边权的差来更新最终的ans

O(q*mlogm)

--------------------------------------------------------------------------------------------------------

最后有两个0 0方便退出询问

但是...也算是个小坑吧

--------------------------------------------------------------------------------------------------------

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

inline int read()
{
    int sum = 0,p = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            p = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (sum *= 10) += ch - '0';
        ch = getchar();
    }
    return sum * p;
}

const int INF = 99999;
int n,m,ans,maxns;
struct edge
{
    int frm,to,wei;
}e[5005];
int fa[105];

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

int findfa(int o)
{
    if(fa[o] == o)
        return o;
    else
        return fa[o] = findfa(fa[o]);
}

int kruskal(int o)
{
    int k = 0;
    maxns = -1;
    for(int i = 1;i <= n;i++)
        fa[i] = i;
    int minn = e[o].wei,maxn = 0;
    for(int i = o;i <= m;i++)
    {
        int a = findfa(e[i].frm);
        int b = findfa(e[i].to);
        if(a == b)
            continue;
        ++k;
        fa[a] = b;
        maxns = max(maxns,e[i].wei);
        if(k == n - 1)
            return 1;
    }
    return 0;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0)
            return 0;
        ans = INF;
        memset(e,0,sizeof(e));
        memset(fa,0,sizeof(fa));
        for(int i = 1;i <= m;i++)
        {
            e[i].frm = read();
            e[i].to = read();
            e[i].wei = read();
        }
        sort(e+1,e+m+1,cmp);
        for(int i = 1;i <= m;i++)
        {
            if(kruskal(i))
                ans = min(ans,maxns - e[i].wei);
        }
        if(ans == INF)
            ans = -1;
        printf("%d
",ans);
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/darlingroot/p/10939929.html