zoukankan      html  css  js  c++  java
  • loj2245 [NOI2014]魔法森林 LCT

    [NOI2014]魔法森林

    链接

    loj

    思路

    a排序,b做动态最小生成树。
    把边拆成点就可以了。
    uoj98.也许lct复杂度写假了、、越卡常,越慢

    代码

    #include <bits/stdc++.h>
    #define ls c[x][0]
    #define rs c[x][1]
    using namespace std;
    const int N = 2e5 + 7;
    int read() {
        int x = 0, f = 1; char s = getchar();
        for (;s > '9' || s < '0'; s = getchar()) if (s == '-') f = -1;
        for (;s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
        return x * f;        
    }
    struct edge {
        int x, y, a, b;
        bool operator < (const edge &zz) const {
            return (a^zz.a) ? a < zz.a : b < zz.b;
        }
    } G[N];
    int f[N], c[N][2], w[N][2], ma[N][2], stak[N], lazy[N], id[N];
    bool isroot(int x) {return c[f[x]][0] == x || c[f[x]][1] == x;}
    void pushup(int x) {
        ma[x][0] = max(max(ma[ls][0], ma[rs][0]), w[x][0]);
        ma[x][1] = max(max(ma[ls][1], ma[rs][1]), w[x][1]);
        id[x] = (ma[x][1] == w[x][1]) ? x : (ma[ls][1] > ma[rs][1]) ? id[ls] : id[rs];
    }
    void tag(int x){swap(ls,rs), lazy[x] ^= 1;}
    void pushdown(int x) {
        if (lazy[x]) {
            if (ls) tag(ls);
            if (rs) tag(rs);
            lazy[x] ^= 1;
        }
    }
    void rotate(int x) {
        int y = f[x], z = f[y], k = c[y][1] == x, w = c[x][!k];
        if (isroot(y)) c[z][c[z][1] == y] = x;
        c[x][!k] = y, c[y][k] = w;
        if (w) f[w] = y;
        f[x] = z, f[y] = x;
        pushup(y);
    }
    void splay(int x) {
        int y = x, z = 0;
        stak[++z] = y;
        while (isroot(y)) stak[++z] = y = f[y];
        while (z) pushdown(stak[z--]);
        while (isroot(x)) {
            y = f[x], z = f[y];
            if (isroot(y)) rotate((c[y][0] == x)^(c[z][0] == y) ? x : y);
            rotate(x);
        }
        pushup(x);
    }
    void access(int x) {
        for (int y = 0; x;x = f[y = x])
            splay(x), rs = y, pushup(x);
    }
    void makeroot(int x) {
        access(x), splay(x);
        tag(x);
    }
    int findroot(int x) {
        access(x), splay(x);
        while(ls) pushdown(x), x = ls;
        return x;
    }
    void split(int x, int y) {
        makeroot(x), access(y), splay(y);
    }
    void link(int x, int y) {
        makeroot(x);
        if (findroot(y) != x) f[x] = y;
    }
    void cut(int x, int y) {
        makeroot(x);
        if (findroot(y) == x && f[x] == y && !rs) {
            f[x] = c[y][0] = 0;
            pushup(y);
        }
    }
    int main() {
        int n = read(), m = read(), ans = 0x3f3f3f3f;
        for (int i = 1; i <= m; ++i)
            G[i].x = read(), G[i].y = read(), G[i].a = read(), G[i].b = read();
        sort(G + 1, G + 1 + m);
        for (int i = 1; i <= m; ++i) {
            if (G[i].x == G[i].y) continue;
            int x = G[i].x, y = G[i].y;
            if (findroot(x) == findroot(y)) {
                split(x, y);
                if (ma[y][1] > G[i].b) {
                    int tmp = id[y];
                    cut(G[tmp - n].x, tmp), cut(G[tmp - n].y, tmp);
                    w[n + i][0] = G[i].a, w[n + i][1] = G[i].b;
                    link(x, n + i), link(n + i, y);
                }
            } else {
                w[n + i][0] = G[i].a, w[n + i][1] = G[i].b;
                link(x, n + i), link(n + i, y);
            }
            if (findroot(1) == findroot(n)) {
                split(1, n);
                ans = min(ans, ma[n][0] + ma[n][1]);
            }
        }
        printf("%d
    ", ans == 0x3f3f3f3f ? -1 : ans);
        return 0;
    }
    
  • 相关阅读:
    问题解决:System.TypeLoadException: 未能从程序集“XXX”中加载类型“XXX
    域名格式验证
    .NET 中String 和StringBuilder 以及他们的区别
    mysql 重设管理员密码 或忘记管理员密码 (必杀)
    CMD 命令
    C# 给多线程传参的三种方式
    django 表单数据的验证实现原理
    django上传文件
    django signal
    Django如何处理语言偏好(根据此可以设置中文)
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10959020.html
Copyright © 2011-2022 走看看