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;
    }
  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/evenbao/p/10146439.html
Copyright © 2011-2022 走看看