[WC2006]水管局長(LCT)

題目大意:

給定一張圖,支持刪邊,求兩點的路徑中全部權值的最大值的最小值,貌似很繞的樣子node

因爲有刪邊,不難想到\(LCT\),又由於\(LCT\)不支持維護圖,並且只有刪邊操做,因而咱們考慮時間回溯。c++

把這道題變成模板有幾個問題:spa

(思路爲我的\(YY\),可能很是麻煩)code

\(1.\)咱們怎麼肯定最後的狀態呢?

首先咱們先用\(map\)存每一條邊,在詢問操做時,每刪一條邊,就把他在\(map\)上去掉,最後剩下的邊即爲最終狀態blog

\(2.\)加邊的時候會出現環該怎麼辦呢?

要讓答案更優,咱們顯然要動態維護最小生成樹,而後維護了最小生成樹後就只要找最小生成樹樹上兩點的最大值了pdo

附上常數極大又十分醜陋的代碼:get

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
il int read() {
    re int x = 0, f = 1; re char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
#define updown(x) swap(ch[1][x], ch[0][x]), tag[x] ^= 1
#define get_fa(x) ch[1][fa[x]] == x
#define isroot(x) ch[1][fa[x]] == x || ch[0][fa[x]] == x
#define _ 150006
int n, m, Q, ans[_], Top, st[_], top, fa[_], tag[_], ch[2][_], val[_], ma[_], id[_];
struct node {int opt, u, v, w;}e[_];
pair<int, int> a[_];
map<pair<int, int>, int> q, Id;
il void pushdown(int x) {
    if(!tag[x]) return;
    if(ch[1][x]) updown(ch[1][x]);
    if(ch[0][x]) updown(ch[0][x]);
    tag[x] = 0;
}
il void pushup(int x) {
    ma[x] = val[x], id[x] = x;
    if(ch[1][x] && ma[x] < ma[ch[1][x]]) ma[x] = ma[ch[1][x]], id[x] = id[ch[1][x]];
    if(ch[0][x] && ma[x] < ma[ch[0][x]]) ma[x] = ma[ch[0][x]], id[x] = id[ch[0][x]];
}
il void rotate(int x) {
    int y = fa[x], z = fa[y], w = get_fa(x), k = get_fa(y);
    ch[w][y] = ch[w ^ 1][x], fa[ch[w ^ 1][x]] = y;
    if(isroot(y)) ch[k][z] = x; fa[x] = z;
    ch[w ^ 1][x] = y, fa[y] = x;
    pushup(y), pushup(x);
}
il void Splay(int x) {
    int y = x;
    st[++ top] = x;
    while(isroot(y)) st[++ top] = y = fa[y];
    while(top) pushdown(st[top --]);
    while(isroot(x)) {
        int y = fa[x];
        if(isroot(y)) rotate(get_fa(x) == get_fa(y) ? y : x);
        rotate(x);
    }
}
il void access(int x) {for(int y = 0; x; x = fa[y = x]) Splay(x), ch[1][x] = y, pushup(x);}
il void makeroot(int x) {access(x), Splay(x), updown(x);}
il int findroot(int x) {
    access(x), Splay(x);
    while(ch[0][x]) x = ch[0][x];
    Splay(x);
    return x;
}
il void spilt(int x, int y) {makeroot(x), access(y), Splay(y);}
il void link(int x, int y) {
    makeroot(x);
    if(findroot(y) != x) fa[x] = y;
}
int main() {
    file(a);
    n = read(), m = read(), Q = read();
    rep(i, 1, m) {
        int u = read(), v = read();
        a[i] = make_pair(u, v), q[make_pair(v, u)] = q[a[i]] = read(), val[i + n] = q[a[i]];
        Id[a[i]] = Id[make_pair(v, u)] = i;
    }
    rep(i, 1, Q) {
        int opt = read(), u = read(), v = read();
        e[i] = (node){opt, u, v, q[make_pair(u, v)]};
    }
    rep(i, 1, Q) 
        if(e[i].opt == 2) q[make_pair(e[i].u, e[i].v)] = q[make_pair(e[i].v, e[i].u)] = 0;
    rep(i, 1, m) {
        if(q[a[i]] == 0) continue;
        if(findroot(a[i].first) == findroot(a[i].second)) {
            spilt(a[i].first, a[i].second); int now = id[a[i].second];
            if(val[i + n] >= val[now]) continue;
            Splay(now), fa[ch[1][now]] = fa[ch[0][now]] = 0;
        }
        link(a[i].first, i + n), link(i + n, a[i].second);
    }
    drep(i, 1, Q) {
        int u = e[i].u, v = e[i].v;
        if(e[i].opt == 2) {
            if(findroot(u) == findroot(v)) {
                spilt(u, v); int now = id[v];
                if(e[i].w >= val[now]) continue;
                Splay(now), fa[ch[1][now]] = fa[ch[0][now]] = 0;
            }
            link(u, Id[make_pair(u, v)] + n), link(Id[make_pair(u, v)] + n, v);
        }
        else spilt(u, v), ans[++ Top] = val[id[v]];
    }
    drep(i, 1, Top) printf("%d\n", ans[i]);
    return 0;
}
相關文章
相關標籤/搜索