• 洛谷P4234 最小差值生成树


    LCT维护生成树

    把边从小到大排序,然后一条一条加边,如果成环就把环上最小的删了,我们得到的第一个生成树就是最小生成树。

    然后之后每一条边都比前面的生成树的最大边大,我们用这条边的权值减去生成树里最小的,更新答案即可。

    因为要维护的是最小值,用排序之后的性质,下表小的值更小来pushup

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    using namespace std;
    typedef long long LL;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            ret = (ret << 3) + (ret << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -ret : ret;
    }
    inline int lcm(int a, int b){ return a / __gcd(a, b) * b; }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 500005;
    int n, m, cnt, tot, cur, ans, val[N], fa[N], ch[N][2], rev[N], id[N], st[N];
    bool vis[N];
    struct Edge {
        int u, v, w;
        bool operator < (const Edge &rhs) const {
            return w < rhs.w;
        }
    } e[N];
    
    int newNode(int x){
        ++ tot;
        val[tot] = x, id[tot] = tot;
        rev[tot] = ch[tot][0] = ch[tot][1] = fa[tot] = 0;
        return tot;
    }
    
    bool isRoot(int x){
        return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
    }
    
    void reverse(int x){
        rev[x] ^= 1, swap(ch[x][0], ch[x][1]);
    }
    
    void push_up(int x){
        id[x] = x;
        int l = ch[x][0], r = ch[x][1];
        if(id[l] > n && (id[x] <= n || id[x] > id[l])) id[x] = id[l];
        if(id[r] > n && (id[x] <= n || id[x] > id[r])) id[x] = id[r];
    }
    
    void push_down(int x){
        if(rev[x]){
            int l = ch[x][0], r = ch[x][1];
            if(l) reverse(l);
            if(r) reverse(r);
            rev[x] ^= 1;
        }
    }
    
    void rotate(int x){
        int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
        ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
        if(!isRoot(y)) ch[z][ch[z][1] == y] = x;
        fa[x] = z, fa[y] = x, ch[x][p] = y;
        push_up(y), push_up(x);
    }
    
    void splay(int x){
        int pos = 0; st[++pos] = x;
        for(int i = x; !isRoot(i); i = fa[i]) st[++pos] = fa[i];
        while(pos) push_down(st[pos--]);
        while(!isRoot(x)){
            int y = fa[x], z = fa[y];
            if(!isRoot(y)){
                (ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);
            }
            rotate(x);
        }
        push_up(x);
    }
    
    void access(int x){
        for(int p = 0; x; p = x, x = fa[x]){
            splay(x), ch[x][1] = p, push_up(x);
        }
    }
    
    void makeRoot(int x){
        access(x), splay(x), reverse(x);
    }
    
    void link(int x, int y){
        makeRoot(x);
        fa[x] = y;
    }
    
    int findRoot(int x){
        access(x), splay(x);
        while(ch[x][0]) push_down(x), x = ch[x][0];
        splay(x);
        return x;
    }
    
    void split(int x, int y){
        makeRoot(x), access(y), splay(y);
    }
    
    bool isConnect(int x, int y){
        makeRoot(x);
        return findRoot(y) == x;
    }
    
    int main(){
    
        n = read(), m = read();
        for(int i = 1; i <= m; i ++){
            e[i].u = read(), e[i].v = read(), e[i].w = read();
        }
        ans = INF, cur = 1;
        sort(e + 1, e + m + 1);
        for(int i = 1; i <= n; i ++) newNode(0);
        for(int i = 1; i <= m; i ++) newNode(e[i].w);
        for(int i = 1; i <= m; i ++){
            int u = e[i].u, v = e[i].v, w = e[i].w;
            if(u == v) continue;
            if(!isConnect(u, v)){
                link(u, i + n), link(i + n, v);
                vis[i] = true, cnt ++;
            }
            else{
                split(u, v);
                int tmp = id[v];
                splay(tmp);
                fa[ch[tmp][0]] = fa[ch[tmp][1]] = 0;
                ch[tmp][0] = ch[tmp][1] = 0;
                vis[tmp - n] = false, vis[i] = true;
                link(u, i + n), link(i + n, v);
                while(!vis[cur]) cur ++;
            }
            if(cnt == n - 1) ans = min(ans, w - e[cur].w);
        }
        cout << ans << endl;
        return 0;
    }
    
    
  • 相关阅读:
    1099. Build A Binary Search Tree (30)
    两个新事物
    time.h
    Nohup命令
    进程锁
    C++中虚析构函数的作用
    c++ 修改stl set中的元素
    STL迭代器辅助函数——advance
    CTreeCtrl 控件使用总结
    关于stl advance函数移动步数超过容器大小(越界)的研究
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/11232377.html
Copyright © 2020-2023  润新知