zoukankan      html  css  js  c++  java
  • [NOI 2014] 魔法森林

    [题目链接]

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

    [算法]

             首先离线 , 将边按A值从小到大排序

             然后用LCT动态维护以B值为关键字的最小生成树即可

             时间复杂度 : O(NlogN ^ 2)

    [代码]

             

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e5 + 10;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const ll inf = 2e9;
    
    struct edge
    {
            int x , y , a , b;
    } e[MAXN];
    
    int n , m;
    
    struct Link_Cut_Tree
    {
            struct Node
            {
                    int father , son[2] , id , mx , value;
                    bool tag;
            }    a[MAXN];
    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].b;
                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 bool connected(int x , int y)
        {
                return (find_root(x) == find_root(y));
            }
            inline int query(int x , int y)
            {
                    split(x , y);
                    return a[y].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.a < b.a;
    }
    
    int main()
    {
    
            read(n); read(m);
            for (int i = 1; i <= m; i++)
            {
                    read(e[i].x); read(e[i].y);
                    read(e[i].a); read(e[i].b);
            }
            sort(e + 1 , e + m + 1 , cmp);
            LCT.init();
            int ans = inf;
            for (int i = 1; i <= m; i++)
            {
                    if (LCT.connected(e[i].x , e[i].y))
                    {    
                            int id = LCT.query(e[i].x , e[i].y);
                            if (id - n > 0 && e[i].b < e[id - n].b)
                            {
                                    LCT.cut(e[id - n].x , id);
                                    LCT.cut(e[id - n].y , id);
                                    LCT.link(e[i].x , i + n);
                                    LCT.link(e[i].y , i + n);
                            }
                    } else
                    {
                            LCT.link(e[i].x , i + n);
                            LCT.link(e[i].y , i + n);
                    }
                    if (LCT.connected(1 , n))
                            chkmin(ans , e[i].a + e[LCT.query(1 , n) - n].b);        
            }
            if (LCT.connected(1 , n)) printf("%d
    " , ans);
            else printf("-1
    ");
            
            return 0;
        
    }
  • 相关阅读:
    SQL的四种连接-左外连接、右外连接、内连接、全连接
    查看Linux下端口占用情况的命令
    linux的命令(1)
    xsheell的下载安装初级使用
    日交易,根据权重分配流量的算法,根据权重和交易笔数
    根据权重挑选通道的简单算法
    Java中的String与常量池
    JAVA虚拟机内存分配与回收机制
    JVM 内部运行线程介绍
    AspectJ切入点语法详解
  • 原文地址:https://www.cnblogs.com/evenbao/p/10159298.html
Copyright © 2011-2022 走看看