• P4172 [WC2006]水管局长


    [LCT]P4172水管局长

    (Solution)

    如果没有删除,那么就是维护一个最小生成树,然后倍增求两点之间的最大边权(货车运输).

    因为有删边操作,想到LCT,但这是删除,最大值不满足减法,所以不好搞。

    但注意到只有删除没有添加,所以我们可以倒过来处理,一条一条边link维护最小生成树以及两点间最大值,这样最大值就变成可加的了。

    倒着处理,如果要加一条边u->v,那么先查询u->v的最大边权(假如这条边为x->y),如果要加的边权比这还大,那么就忽略(贪心),否则就删掉x->y,再link(u, v). (ps:因为要知道x->y对应的边是什么,所以可以用 map<pair<int, int> >)

    一个小技巧:因为LCT维护的是点上的信息,所以我们边化点.如果要连xy,且这条边编号z,那么就执行link(x, z + n), link(z + n, y)

    (Source)

    #include <map>
    #include <cmath>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define fir first
    #define sec second
    #define pb push_back
    #define mp make_pair
    #define LL long long
    #define INF (0x3f3f3f3f)
    #define mem(a, b) memset(a, b, sizeof (a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(x) cout << #x << " = " << x << endl
    #define tralve(i, x) for (register int i = head[x]; i; i = nxt[i])
    #define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
    #define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
    #define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
    
    namespace io {
        static char buf[1<<21], *pos = buf, *end = buf;
        inline char getc()
        { return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
        inline int rint() {
            register int x = 0, f = 1;register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline LL rLL() {
            register LL x = 0, f = 1; register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline void rstr(char *str) {
            while (isspace(*str = getc()));
            while (!isspace(*++str = getc()))
                if (*str == EOF) break;
            *str = '';
        }
        template<typename T> 
            inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
        template<typename T>
            inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }    
    }
    using namespace io;
    
    const int N = 3e5 + 10;
    
    int n, m;
    struct Edge { int x, y, z; } edge[N];
    bool cmp (Edge a, Edge b) { return a.z < b.z; }
    struct Query { int op, x, y, id;} q[N];
    map< pair<int, int>, int> Id;
    bool del[N];
    
    namespace LCT {
    #define ls (ch[x][0])
    #define rs (ch[x][1])
    #define chk(x) (ch[fa[x]][1] == x)
        int val[N], mx[N], ch[N][2], fa[N], rev[N];
        bool isroot(int x) { return x != ch[fa[x]][0] && x != ch[fa[x]][1]; }
        void pushup(int x) {
            mx[x] = val[x];
            if (edge[mx[x]].z < edge[mx[ch[x][0]]].z) mx[x] = mx[ch[x][0]];
            if (edge[mx[x]].z < edge[mx[ch[x][1]]].z) mx[x] = mx[ch[x][1]]; 
        }
        void pushdown(int x) {
            if (rev[x]) {
                swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]);
                rev[ls] ^= 1, rev[rs] ^= 1;
                rev[x] = 0;
            }
        }
        void rotate(int x) {
            int y = fa[x], z = fa[y], k = chk(x), tmp = ch[x][k ^ 1];
            ch[y][k] = tmp, fa[tmp] = y;
            if (!isroot(y)) ch[z][chk(y)] = x; fa[x] = z;
            ch[x][k ^ 1] = y, fa[y] = x;
            pushup(y); pushup(x);
        }
        int stk[N], top;
        void splay(int x) {
            stk[top = 1] = x; for (int i = x; !isroot(i); i = fa[i]) stk[++top] = fa[i];
            while (top) pushdown(stk[top--]);
            while (!isroot(x)) {
                int y = fa[x], z = fa[y];
                if (!isroot(y))
                    if (chk(x) == chk(y)) rotate(y);
                    else rotate(x);
                rotate(x);
            }
        }
        void access(int x) { for (int y = 0; x; x = fa[y = x]) splay(x), ch[x][1] = y, pushup(x); }
        int findroot(int x) { access(x); splay(x); pushdown(x);
            while (ch[x][0])  x = ch[x][0], pushdown(x);
            splay(x); return x;
        }
        void makeroot(int x) { access(x); splay(x); swap(ch[x][0], ch[x][1]); rev[x] ^= 1; }
        void split(int x, int y) { makeroot(x); access(y); splay(y); }
        void link(int x, int y) { makeroot(x); fa[x] = y; }
        void cut(int x, int y) { split(x, y); fa[x] = ch[y][0] = 0; }
    }
    using namespace LCT;
    int ans[N];
    int main() {
    #ifndef ONLINE_JUDGE
        file("P4172");
    #endif
        int Q;
        n = rint(), m = rint(), Q = rint();
        For (i, 1, m) {
            edge[i].x = rint(), edge[i].y = rint(), edge[i].z = rint();
            if (edge[i].x > edge[i].y) swap(edge[i].x, edge[i].y);
        }
        sort(edge + 1, edge + 1 + m, cmp);
        For (i, 1, m) Id[mp(edge[i].x, edge[i].y)] = i;
        For (i, 1, Q) {
            q[i].op = rint(), q[i].x = rint(), q[i].y = rint();
            if (q[i].x > q[i].y) swap(q[i].x, q[i].y);
            if (q[i].op == 2) {
                q[i].id = Id[mp(q[i].x, q[i].y)];
                del[q[i].id] = 1;
            }
        }
        For (i, n + 1, m + n)
            mx[i] = val[i] = i - n;
    
        int sum = 0;
        For (i, 1, m) {
            if (del[i]) continue;
            if (sum == n - 1) break;
            int x = edge[i].x, y = edge[i].y;
            if (findroot(x) != findroot(y)) {
                link(x, i + n); link(i + n, y);
                sum ++;
            }
        }
        
        Forr (i, Q, 1) {
            int x = q[i].x, y = q[i].y;
            if (q[i].op == 1) {
                split(x, y); ans[i] = edge[mx[y]].z;
            } else {
                split(x, y);
                int t = mx[y];
                if (edge[q[i].id].z < edge[t].z) {
                    cut(edge[t].x, t + n); cut(t + n, edge[t].y);
                    link(x, q[i].id + n); link(y, q[i].id + n);
                }
            }
        }
        For (i, 1, Q) if (q[i].op == 1) printf("%d
    ", ans[i]);
    }
    
  • 相关阅读:
    指定pdf的格式
    iptables 防火墙
    jumpserver2
    jquery UI
    python 自动化审计
    Jumpserver
    认识二进制安全与漏洞攻防技术 (Windows平台)
    将这段美化的css代码
    pycharm
    android Tips
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10458407.html
Copyright © 2020-2023  润新知