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

    https://www.luogu.org/problemnew/show/P2387

    考虑先将所有边按 a 值排序,依次加入每一条边,如果这条边的两个端点 ( l, r ) 之间的简单路径中 b 的最大值大于这条边的 b 值,删掉最大的一条边,加入这条边,如果 l 和 r 不连通,则直接 link

    需要注意的是将边权转换为点权,将第 i 条边变成编号为 i + n 的点,维护最大值的位置就可以了

    这题还有自环( 坑了我半个小时 )

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef unsigned long long ull;
    typedef long long ll;
    
    template <typename _T>
    inline void read(_T &f) {
        f = 0; _T fu = 1; char c = getchar();
        while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
        while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
        f *= fu;
    }
    
    const int N = 150000 + 10;
    
    struct ele {
        int u, v, a, b;
        bool operator < (const ele A) const {return a < A.a;}
    }p[N];
    
    int fa[N], ch[N][2], maxn[N], val[N], rev[N], wz[N], st[N], f[N], n, m, len, ans = INT_MAX;
    
    int isroot(int u) {return ch[fa[u]][0] != u && ch[fa[u]][1] != u;}
    
    int get(int u) {return ch[fa[u]][1] == u;}
    
    void update(int u) {
        maxn[u] = val[u]; wz[u] = u;
        if(maxn[ch[u][0]] > maxn[u] && ch[u][0]) maxn[u] = maxn[ch[u][0]], wz[u] = wz[ch[u][0]];
        if(maxn[ch[u][1]] > maxn[u] && ch[u][1]) maxn[u] = maxn[ch[u][1]], wz[u] = wz[ch[u][1]];
    }
    
    void pushdown(int u) {
        if(rev[u]) {
            swap(ch[u][0], ch[u][1]);
            rev[ch[u][0]] ^= 1;
            rev[ch[u][1]] ^= 1;
            rev[u] ^= 1;
        }
    }
    
    void rotate(int u) {
        int old = fa[u], oldd = fa[old], k = get(u);
        if(!isroot(old)) ch[oldd][get(old)] = u; fa[u] = oldd;
        ch[old][k] = ch[u][k ^ 1]; fa[ch[u][k ^ 1]] = old;
        fa[old] = u; ch[u][k ^ 1] = old;
        update(old); update(u);
    }
    
    void splay(int u) {
        st[len = 1] = u;
        for(int i = u; !isroot(i); i = fa[i]) st[++len] = fa[i];
        for(int i = len; i >= 1; i--) pushdown(st[i]);
        for(; !isroot(u); rotate(u)) if(!isroot(fa[u])) rotate(get(u) == get(fa[u]) ? fa[u] : u);
    }
    
    void access(int u) {
        for(int i = 0; u; i = u, u = fa[u]) {
            splay(u);
            ch[u][1] = i;
            update(u);
        }
    }
    
    void makeroot(int u) {
        access(u);
        splay(u);
        rev[u] ^= 1;
    }
    
    int findroot(int u) {
        access(u); splay(u);
        while(ch[u][0]) u = ch[u][0];
        return u;
    }
    
    void link(int u, int v) {
        makeroot(u);
        fa[u] = v;
    }
    
    void cut(int u, int v) {
        makeroot(u);
        access(v);
        splay(v);
        fa[u] = ch[v][0] = 0;
        update(v);
    }
    
    int query(int u, int v) {
        makeroot(u);
        access(v);
        splay(v);
        return wz[v]; 
    }
    
    int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}
    
    int main() {
        read(n); read(m);
        for(int i = 1; i <= n; i++) f[i] = i;
        for(int i = 1; i <= m; i++) {
            read(p[i].u); read(p[i].v);
            read(p[i].a); read(p[i].b);
        }
        sort(p + 1, p + m + 1);
        for(int i = 1; i <= m; i++) {
            int x = p[i].u, y = p[i].v;
            int A = p[i].a, B = p[i].b;
            if(find(x) != find(y)) {
                f[find(x)] = find(y);
                val[i + n] = maxn[i + n] = B;
                link(x, i + n); link(y, i + n);
            } else {
                if(x == y) continue;
                int weizhi = query(x, y);
                if(p[weizhi - n].b > B) {
                    cut(p[weizhi - n].u, weizhi);
                    cut(p[weizhi - n].v, weizhi);
                    val[i + n] = maxn[i + n] = B;
                    link(x, i + n); link(y, i + n);
                }
            }
            if(find(1) == find(n)) ans = min(ans, p[query(1, n) - n].b + A);
        }
        if(ans == INT_MAX) cout << -1 << endl; else cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    做的简单的一个静态web服务器,遇到个bug, 提示osError,这点一不小心就错了,特地记下来,加深记忆,socket须先绑定,再listen,如果是先listen再绑定,系统会自动分配一个端口,而程序绑定不了
    all,any函数
    【转】利用matlab生成随机数函数
    时间转换与星期推算(Matlab版)
    Matlab 多项式拟合、稳健滤波等实用函数
    MySQL索引与优化策略
    Linux系统性能监控
    MySQL备份与复制
    关于解决android4.0系统中菜单无法添加Icon的问题
    关于Android LayoutInflater的解释
  • 原文地址:https://www.cnblogs.com/LJC00118/p/9562859.html
Copyright © 2011-2022 走看看