• [Luogu] 最小差值生成树


    https://www.luogu.org/recordnew/show/6125570

    思路就是巧妙的枚举所有的生成树,取最优值
    首先按照边权排序
    找出第一颗最小生成树(l, r),其中l表示最小边的编号,r表示最大边的编号
    然后从r+1号边开始倒序枚举各边,求出第二颗最小生成树(当然也可能不存在)(l_2, r_2), r_2 = r + 1.
    这样的话就省去了多条最小边的枚举
    比如若从2 -- l_2-1中任选一条边作为最小边开始查询最大生成树,那么最大边一定为r_2
    这样的话差值不会比(l_2, r_2)这颗生成树更优,所以就简化了算法
    然后从将l_2+1号边作为最小边开始枚举,依次进行下去

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    const int N = 5e4 + 10;
    
    #define gc getchar()
    
    int fa[N];
    struct Node{int u, v, w;} G[N << 2];
    int n, m, Answer = 999999999;
    
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    inline bool cmp(Node a, Node b) {return a.w < b.w;}
    int get_fa(int x) {return fa[x] == x ? x : fa[x] = get_fa(fa[x]);}
    void Printf() {cout << Answer; exit(0);}
    
    void dfs(int start, int how) {
        for(int i = 1; i <= n; i ++) fa[i] = i;
        int tot = 0, Maxn = 0, Minn = 0, Nxt;
        if(how % 2) {//cong xiao dao da
            for(int i = start; i <= m; i ++) {
                int fa_u = get_fa(G[i].u), fa_v = get_fa(G[i].v);
                if(fa_u != fa_v) {
                    fa[fa_u] = fa_v;
                    tot ++;
                    if(tot == n - 1) {Maxn = G[i].w; Nxt = i; break;}
                }
            }
            if(!Maxn) Printf();
            Answer = min(Answer, Maxn - G[start].w);
        } else {
            for(int i = start; i >= 1; i --) {
                int fa_u = get_fa(G[i].u), fa_v = get_fa(G[i].v);
                if(fa_u != fa_v) {
                    fa[fa_u] = fa_v;
                    tot ++;
                    if(tot == n - 1) {Minn = G[i].w; Nxt = i; break;
                    }
                }
            }
            if(!Minn) Printf();
            Answer = min(Answer, G[start].w - Minn);
        }
        dfs(Nxt + 1, how + 1);
    }
    
    int main() {
        n = read();
        m = read();
        for(int i = 1; i <= m; i ++) G[i].u = read(), G[i].v = read(), G[i].w = read();
        sort(G + 1, G + m + 1, cmp);
        dfs(1, 1);
        return 0;
    }
  • 相关阅读:
    sql查询自然数判断
    esayswool_admin的3个坑
    debian安装easyswoole
    微软浏览器冲浪小游戏
    php程序的安装和composer
    图片搬运工
    热血高校这部电影中的内含文化
    Google日本語入力的使用方法,基本的快捷键。
    PHP截取两个指定字符中间的字符
    php去除字符串中的HTML标签
  • 原文地址:https://www.cnblogs.com/shandongs1/p/8480832.html
Copyright © 2020-2023  润新知