• NOI2014 魔法森林


    Description

    link

    题意概述:给一张图,每条边有两个相关量(设其为 (a_i) , (b_i)

    求图上一条从(1)(n)的路径,使得在分别使路径上 $ a $ , (b) 最大值最小的时候,(a_{max}+b_{max}) 得到最小值

    (n leq 2 imes10^5)

    Solution

    首先这个题涉及到连边的问题和维护路径上的信息,我们可以用 (LCT) 解决,同时需要点边转化,把数组开大一点

    这题比较巧妙的一个思路就在我们可以考虑 (sort) 一发,把 (a) 搞成单调增的一维

    然后 (LCT) 处理 (b) 就好了,这个就是 (update) 最大值,加边的时候遇到环就拆边就好了

    如果不懂怎么点边转化的可以看我的博客WC2006水管局长

    (显然的方法是去看@Flash_Hu大佬的LCT总结)

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm {
    inline int read() {
        int res = 0, f = 1;
        char k;
        while (!isdigit(k = getchar()))
            if (k == '-')
                f = -1;
        while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
        return res * f;
    }
    const int N = 5e5 + 10;
    struct node {
        int from, to, a, b;
        bool operator<(const node &x) const { return a == x.a ? b < x.b : a < x.a; }
    } e[N << 2];
    int f[N], c[N][2], maxx[N], st[N], n, m, ans = 1e15 + 10, del = 262144;
    bool r[N];
    inline bool notroot(int x) { return c[f[x]][0] == x || c[f[x]][1] == x; }
    inline void push_up(int x) {
        maxx[x] = x;
        if (e[maxx[x]].b < e[maxx[c[x][0]]].b)
            maxx[x] = maxx[c[x][0]];
        if (e[maxx[x]].b < e[maxx[c[x][1]]].b)
            maxx[x] = maxx[c[x][1]];
        return;
    }
    inline void push_down(int x) {
        if (r[x]) {
            swap(c[x][0], c[x][1]);
            r[c[x][0]] ^= 1;
            r[c[x][1]] ^= 1;
        }
        return r[x] = 0, void();
    }
    inline void push_all(int x) {
        if (notroot(x))
            push_all(f[x]);
        push_down(x);
    }
    inline void rotate(int x) {
        int y = f[x], z = f[y], k = (c[y][1] == x), w = c[x][!k];
        if (notroot(y))
            c[z][c[z][1] == y] = x;
        c[x][!k] = y;
        c[y][k] = w;
        if (w)
            f[w] = y;
        f[y] = x;
        f[x] = z;
        return push_up(y);
    }
    inline void splay(int x) {
        int y = x;
        push_all(x);
        while (notroot(x)) {
            y = f[x];
            if (notroot(y))
                rotate((c[y][0] == x) ^ (c[f[y]][0] == y) ? x : y);
            rotate(x);
        }
        return push_up(x), void();
    }
    inline void access(int x) {
        for (int y = 0; x; x = f[y = x]) splay(x), c[x][1] = y, push_up(x);
        return;
    }
    inline void makeroot(int x) {
        access(x);
        splay(x);
        r[x] ^= 1;
        return;
    }
    inline int findroot(int x) {
        access(x);
        splay(x);
        while (c[x][0]) x = c[x][0];
        return x;
    }
    inline void link(int id) {
        int y = e[id].from, z = e[id].to;
        makeroot(z);
        f[f[z] = id] = y;
        return;
    }
    
    inline void cut(int x) {
        access(e[x].to);
        splay(x);
        c[x][0] = c[x][1] = f[c[x][0]] = f[c[x][1]] = 0;
        return push_up(x);
    }
    
    signed main() {
        n = read();
        m = read();
        for (int i = 1; i <= m; ++i)
            e[i].from = read() | del, e[i].to = del | read(), e[i].a = read(), e[i].b = read();
        sort(e + 1, e + m + 1);
        for (int i = 1; i <= m; ++i) {
            if (e[i].from == e[i].to)
                continue;
            int y = e[i].from, z = e[i].to;
            makeroot(y);
            if (findroot(z) != y)
                link(i);
            else if (e[i].b < e[maxx[z]].b)
                cut(maxx[z]), link(i);
            makeroot(1 | del);
            if (findroot(1 | del) == findroot(n | del))
                ans = min(ans, e[maxx[n | del]].b + e[i].a);
        }
        printf("%lld
    ", ans == 1e15 + 10 ? -1 : ans);
        return 0;
    }
    }  // namespace yspm
    signed main() { return yspm::main(); }
    
  • 相关阅读:
    socket tools
    AcWing 1172 祖孙询问
    AcWing 1170 排队布局
    AcWing 393 雇佣收银员
    AcWing 362. 区间
    基于最短路的差分约束模型
    AcWing 1169 分糖果
    树上差分
    AcWing 352 . 闇の連鎖
    AcWing 1171. 距离
  • 原文地址:https://www.cnblogs.com/yspm/p/12369475.html
Copyright © 2020-2023  润新知