zoukankan      html  css  js  c++  java
  • [WC 2006] 水管局长

    [题目链接]

              https://www.lydsy.com/JudgeOnline/problem.php?id=2594

    [算法]

            首先离线 , 将删边操作转化为倒序加边

            假设我们已经维护出了一棵最小生成树T , 若加入了一条边(u , v , w) , 那么形成了一个环 ,考虑kruskal算法的执行过程 :

            若w < 环上的边权最大值 , 那么可以将(u , v , w)加入 , 并将环上边权最大的边删除

            可以使用LCT维护

            时间复杂度 : O(NlogN ^ 2) , 注意常数优化

    [代码]

             

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 3e5 + 10;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    struct edge
    {
        int u ,  v , w;
    } e[MAXN << 1];
    struct query
    {
        int type;
        int u , v;
    } que[MAXN << 1];
    
    int n , m , q;
    int fa[MAXN];
    bool flg[MAXN];
    
    struct Link_Cut_Tree
    {
        struct Node
        {
            int father , son[2] , mx , value , id;
            bool tag;
        } a[MAXN << 2];
        inline void update(int x)
        {
            a[x].mx = a[x].value;
            a[x].id = x;
            if (a[x].son[0])
            {
                if (a[a[x].son[0]].mx > a[x].mx)
                {
                    a[x].mx = a[a[x].son[0]].mx;
                    a[x].id = a[a[x].son[0]].id;
                }
            }
            if (a[x].son[1])
            {
                if (a[a[x].son[1]].mx > a[x].mx)
                {
                    a[x].mx = a[a[x].son[1]].mx;
                    a[x].id = a[a[x].son[1]].id;
                }
            }
        }
        inline void init()
        {
            for (int i = n + 1; i <= n + m + 1; i++)
            {
                a[i].mx = a[i].value = e[i - n].w;
                a[i].id = i;
            }
        }
        inline void pushdown(int x)
        {
            if (a[x].tag)
            {
                swap(a[x].son[0] , a[x].son[1]);
                a[a[x].son[0]].tag ^= 1;
                a[a[x].son[1]].tag ^= 1;
                a[x].tag = false;
            }
        }
        inline bool get(int x)
        {
            pushdown(a[x].father);
            return a[a[x].father].son[1] == x;
        }
        inline bool nroot(int x)
        {
            return a[a[x].father].son[0] == x | a[a[x].father].son[1] == x;
        }
        inline void rotate(int x)
        {
            int f = a[x].father , g = a[f].father;                        
            int tmpx = get(x) , tmpf = get(f);
            int w = a[x].son[tmpx ^ 1];
            if (nroot(f)) a[g].son[tmpf] = x;
            a[x].son[tmpx ^ 1] = f;
            a[f].son[tmpx] = w;
            if (w) a[w].father = f;
            a[f].father = x;
            a[x].father = g;
            update(f);
        }
        inline int find_root(int x)
        {
            access(x);
            splay(x);
            while (a[x].son[0])
            {
                pushdown(x);
                x = a[x].son[0];
            }
            return x;
        }
        inline void access(int x)
        {
            for (int y = 0; x; x = a[y = x].father)
            {
                splay(x);
                a[x].son[1] = y;
                update(x);
            }
        }
        inline void splay(int x)
        {
            int y = x , z = 0;
            static int st[MAXN];
            st[++z] = y;
            while (nroot(y)) st[++z] = y = a[y].father;
            while (z) pushdown(st[z--]);
            while (nroot(x))
            {
                int y = a[x].father , z = a[y].father;
                if (nroot(y))
                    rotate((a[y].son[0] == x) ^ (a[z].son[0] == y) ? x : y);
                rotate(x);
            }
            update(x);
        }
        inline void split(int x , int y)
        {
            make_root(x);
            access(y);
            splay(y);    
        } 
        inline void make_root(int x)
        {
            access(x);
            splay(x);
            a[x].tag ^= true;
            pushdown(x);
        }
        inline void link(int x , int y)
        {
            make_root(x);
            if (find_root(y) != x) a[x].father = y;
        }
        inline void cut(int x , int y)
        {
            make_root(x);
            if (find_root(y) == x && a[x].father == y && !a[x].son[1])
            {
                a[x].father = a[y].son[0] = 0;
                update(y);
            }
        }
        inline int query(int x)
        {
            return a[x].id;
        }
    } LCT;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline bool cmp(edge a , edge b)
    {
        return a.w < b.w;    
    }
    inline int get_root(int x)
    {
        if (fa[x] == x) return x;
        else return fa[x] = get_root(fa[x]);
    }
    
    int main()
    {
        
        read(n); read(m); read(q);
        for (int i = 1; i <= m; i++)
        {
            read(e[i].u);
            read(e[i].v);
            read(e[i].w);    
            if (e[i].u > e[i].v) swap(e[i].u , e[i].v);
        }
        sort(e + 1 , e + m + 1 , cmp);
        map< pair<int , int> , int> mp;
        for (int i = 1; i <= m; i++) 
            mp[make_pair(e[i].u , e[i].v)] = i;
        for (int i = 1; i <= q; i++)
        {
            read(que[i].type);
            read(que[i].u);
            read(que[i].v);
            if (que[i].u > que[i].v) swap(que[i].u , que[i].v);
            if (que[i].type == 2)
                flg[mp[make_pair(que[i].u , que[i].v)]] = true;
        }
        LCT.init();
        for (int i = 1; i <= n; i++) fa[i] = i;
        for (int i = 1; i <= m; i++)
        {
            if (flg[i]) continue;
            int su = get_root(e[i].u) , sv = get_root(e[i].v);
            if (su != sv)
            {
                fa[su] = sv;
                LCT.link(e[i].u , i + n);
                LCT.link(e[i].v , i + n);
            }
        }
        vector< int > ans;
        for (int i = q; i >= 1; i--)
        {
            if (que[i].type == 1)
            {
                LCT.split(que[i].u , que[i].v);
                ans.push_back(e[LCT.query(que[i].v) - n].w);    
            } else
            {
                LCT.split(que[i].u , que[i].v);
                int id = LCT.query(que[i].v);
                if (e[mp[make_pair(que[i].u , que[i].v)]].w < e[id - n].w)
                {
                    LCT.cut(e[id - n].u , id);
                    LCT.cut(e[id - n].v , id);
                    LCT.link(que[i].u , mp[make_pair(que[i].u , que[i].v)] + n);
                    LCT.link(que[i].v , mp[make_pair(que[i].u , que[i].v)] + n);
                }
            }
        }
        reverse(ans.begin() , ans.end());
        for (unsigned i = 0; i < ans.size(); i++) printf("%d
    " , ans[i]);
        
        return 0;
    }
  • 相关阅读:
    Problem S: 分数类的模板数组类
    Problem E: 向量的运算
    Problem D: 强悍的矩阵运算来了
    Problem C: Person类与Student类的关系
    Problem B: 还会用继承吗?
    Problem A: 求个最大值
    Problem B: 数组类(II)
    树的直径题集
    LCA题集
    线段树总结
  • 原文地址:https://www.cnblogs.com/evenbao/p/10146439.html
Copyright © 2011-2022 走看看