[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;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/10159298.html