zoukankan      html  css  js  c++  java
  • bzoj 4998 星球联盟

    新技能 get √ :LCT 维护边双连通分量

    这题题意就是动态加边,每次求边的两端是否在一个边双连通分量里,输出 "No" 或者边双连通分量的大小

    可以用两个并查集分别记录连通性和双连通性,如果还没连通就是 "No" 并在 LCT 上连边,否则直接把这条链 split 出来查即可

    注意 LCT 维护的是双连通分量,所以每次跳 fa 的时候不再是 fa,而是 fa 所在的双连通分量

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0,f = 1; char ch = getchar();
        for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;
        for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 200010;
    int par[maxn], par2[maxn], size[maxn], ans;
    inline int find(int x) {return x == par[x] ? x : par[x] = find(par[x]);}
    inline int find2(int x) {return x == par2[x] ? x : par2[x] = find2(par2[x]);}
    int n, m, p;
    #define ls ch[x][0]
    #define rs ch[x][1]
    int ch[maxn][2], fa[maxn], rev[maxn], st[maxn], top;
    inline int isroot(int x) { return ch[find(fa[x])][0] != x && ch[find(fa[x])][1] != x; }
    inline void pushdown(int x) {
        if(rev[x]) {
            swap(ls, rs); 
            if(ls) rev[ls] ^= 1; 
            if(rs) rev[rs] ^= 1;
            rev[x] = 0;
        }
    }
    inline void rotate(int x) {
        int y = find(fa[x]), z = find(fa[y]);
        int l = (ch[y][1] == x), r = l ^ 1;
        if(!isroot(y)) ch[z][ch[z][1] == y] = x;
        fa[x] = z; fa[ch[x][r]] = y; fa[y] = x;
        ch[y][l] = ch[x][r]; ch[x][r] = y;
    }
    inline void splay(int x) {
        st[top = 1] = x;
        for(int i=x;!isroot(i);i=find(fa[i])) st[++top] = find(fa[i]);
        for(int i=top;i;i--) pushdown(st[i]);
        //PUSHDOWN(x);
        //cout << x << endl;
        while(!isroot(x)) {
            int y = find(fa[x]), z = find(fa[y]);
            if(!isroot(y)) {
                if(ch[z][0] == y ^ ch[y][0] == x) rotate(x);
                else rotate(y);
            } rotate(x);
        }
    }
    inline void access(int x) {
        for(int y = 0; x; splay(x), rs = y, y = x, x = find(fa[x]));
    }
    inline void makeroot(int x) {
        access(x); splay(x); rev[x] ^= 1;
    }
    inline void link(int x, int y) {
        makeroot(x); fa[x] = y;
    }
    void dfs(int x, int pre) {
        if(!x) return;
        ans += size[x];
        if(x != pre) size[pre] += size[x], par[x] = pre;
        dfs(ls, pre); dfs(rs, pre);
    }
    inline void lnk(int u, int v) {
        ans = 0;
        if(find2(u) != find2(v)) {
            par2[par2[u]] = par2[v];
            //cout << u << " " << v << endl;
            link(u, v);
        }
        else {
            makeroot(u); access(v); splay(v); dfs(v, v);
        }
    }
    int main() {
        n = read(), m = read(), p = read();
        rep(i, 1, n) size[i] = 1, par[i] = i, par2[i] = i;
        rep(i, 1, m) {
            int u = find(read()), v = find(read());
            lnk(u, v);
        }
        rep(i, 1, p) {
            int u = find(read()), v = find(read()); lnk(u, v);
            printf(ans ? "%d
    " : "No
    ", ans);
        }
    }
    View Code
  • 相关阅读:
    linux,windows kettle安装方法
    等待事件分类
    分析函数详细例子
    v$session中不同连接方式module,program的区别
    charles Glist发布设置
    charles 发布Glist
    charles 工具菜单总结
    charles 高级批量请求
    charles 批量重复请求/重复发包工具
    charles 重写工具/rewrite Srttings
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10634512.html
Copyright © 2011-2022 走看看