• bzoj2594 [Wc2006]水管局长数据加强版


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2594

    【题解】

    不难考虑到这样一个性质:u->v路径上最大边最小,一定在MST上。

    这个可以用kruskal来证明

    有了这个结论就这题很显然就可做了。

    考虑时光倒流,变成加边、询问u->v路径上最大边最小值。

    可以用LCT维护边权最大值以及出现位置,即可。

    复杂度$O(nlog(n+m))$。

    竟然1A了。。还刚好25s。感觉非常优秀。

    竟然只写了20min,代码可读性很高

    # include <map>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1.5e6 + 10, N = 1e5 + 10;
    const int mod = 1e9+7;
    
    // 性质:u->v路径上最大边最小,一定在MST上。 
    
    int n, m, ans[N];
    bool v[M]; 
    map<int, int> mp[N];
    
    inline int getint() {
        char ch = getchar(); int x = 0; 
         while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
        return x;
    }
    
    struct pa {
        int t, a, b;
        pa() {}
        pa(int t, int a, int b) : t(t), a(a), b(b) {}
    }q[N]; 
    
    struct edge {
        int u, v, t;
        edge() {}
        edge(int u, int v, int t) : u(u), v(v), t(t) {}
        friend bool operator < (edge a, edge b) {
            return a.t < b.t;
        }
    }e[M]; 
    
    struct us {
        int fa[N], n;
        inline void set(int _n) {
            n = _n; for (int i=1; i<=n; ++i) fa[i] = i;
        }
        inline int getf(int x) {
            return fa[x] == x ? x : fa[x] = getf(fa[x]);
        }
        inline void un(int fx, int fy) {
            fa[fx] = fy;
        }
    }U;
     
    struct LCT {
        int ch[M][2], fa[M], val[M], mx[M], id[M];
        bool rev[M]; 
        inline void set() {
            memset(ch, 0, sizeof ch);
            memset(fa, 0, sizeof fa);
            memset(val, 0, sizeof val);
            memset(mx, 0, sizeof mx);
            memset(rev, 0, sizeof rev);
            memset(id, 0, sizeof id); 
        }
        # define ls ch[x][0]
        # define rs ch[x][1] 
        inline void up(int x) {
            if(!x) return ;
            mx[x] = val[x]; id[x] = x;
            if(mx[x] < mx[ls]) mx[x] = mx[ls], id[x] = id[ls];
            if(mx[x] < mx[rs]) mx[x] = mx[rs], id[x] = id[rs]; 
        }
        inline void pushrev(int x) {
            if(!x) return ; 
            swap(ls, rs); 
            rev[x] ^= 1;
        }
        inline void down(int x) {
            if(!x || !rev[x]) return ;
            pushrev(ls), pushrev(rs);
            rev[x] = 0;
        }
        # undef ls
        # undef rs
        inline bool isrt(int x) {
            return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
        }
        inline void rotate(int x) {
            int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1; 
            if(!isrt(y)) ch[z][ch[z][1] == y] = x;
            fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
            ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
            up(y); up(x);
        }
        int st[M]; 
        inline void splay(int x) {
            int stn = 0, tx = x;
            while(!isrt(tx)) st[++stn] = tx, tx = fa[tx];
            st[++stn] = tx;
            for (int i=stn; i; --i) down(st[i]);
            while(!isrt(x)) {
                int y = fa[x], z = fa[y];
                if(!isrt(y)) {
                    if((ch[y][0] == x) ^ (ch[z][0] == y)) rotate(x);
                    else rotate(y);
                }
                rotate(x);
            }
        }
        inline int access(int x) {
            int t = 0;
            for (; x; t = x, x = fa[x]) {
                splay(x); 
                ch[x][1] = t;
                up(x);
            }
            return t;
        }
        inline void makeroot(int x) {
            access(x); splay(x); pushrev(x);
        }
        inline void link(int x, int y) {
            makeroot(x); fa[x] = y;
        } 
        inline int cut(int x, int y) {
            makeroot(x); access(y); splay(y); ch[y][0] = fa[x] = 0; up(y); 
        }
        inline int split(int x, int y) {
            makeroot(x); access(y); splay(y); return y;
        }
    }T;
    
    int main() {
        n = getint(), m = getint();
        int Q = getint(); U.set(n); T.set(); 
        for (int i=1; i<=m; ++i) e[i].u = getint(), e[i].v = getint(), e[i].t = getint();
        sort(e+1, e+m+1); 
        for (int i=1; i<=m; ++i) mp[e[i].u][e[i].v] = i, mp[e[i].v][e[i].u] = i; 
        for (int i=1; i<=Q; ++i) { 
             q[i].t = getint(); q[i].a = getint(), q[i].b = getint();
            if(q[i].t == 2) v[mp[q[i].a][q[i].b]] = 1; 
        }
        for (int i=1, x; i<=m; ++i) {
            if(v[i]) continue; 
            int fu = U.getf(e[i].u), fv = U.getf(e[i].v);
            if(fu != fv) { 
                x = i+n;
                U.un(fu, fv);
                T.val[x] = e[i].t;
                T.link(e[i].u, x);
                T.link(e[i].v, x);
            }
        }
        for (int i=Q, x, t, y; i; --i) {
            x = T.split(q[i].a, q[i].b); 
            if(q[i].t == 1) ans[i] = T.mx[x];
            else {
                // adde (q[i].a, q[i].b)
                y = n + mp[q[i].a][q[i].b];
                t = e[y-n].t;
                if(t < T.mx[x]) { 
                    T.val[y] = t; t = T.id[x];
                    T.cut(t, e[t-n].u);    
                    T.cut(t, e[t-n].v); 
                    T.link(q[i].a, y);
                    T.link(q[i].b, y);
                }
            }
        }
        for (int i=1; i<=Q; ++i) if(q[i].t == 1) printf("%d
    ", ans[i]); 
        return 0;
    }
    View Code
  • 相关阅读:
    A* 寻路学习
    Tower Defense Toolkit 学习
    Restaurant & Cooking Starter Kit v1.2.1 学习
    常用工具
    Unity 2017 Game Optimizations (Chris Dickinson 著)
    小小小游戏
    支付宝9张图稳扫出敬业福
    支付宝最强集五福教程
    【免费CDN】俄罗斯DDOS-Guard 支持ssl 防御1.5T
    First day with Java :)
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2594.html
Copyright © 2020-2023  润新知