zoukankan      html  css  js  c++  java
  • BZOJ4998 星球联盟(LCT+双连通分量+并查集)

      即要求动态维护边双。出现环时将路径上的点合并即可。LCT维护。具体地,加边成环时makeroot+access+splay一套把这段路径提出来,暴力dfs修改并查集祖先,并将这部分与根断开,视为删除这些点,以后就以并查集中的祖先代替这些点。access时更新每个点的父亲。注意由于之前的删点操作,判断是否连通需要另开一个并查集而不能findroot。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    #define lson tree[k].ch[0]
    #define rson tree[k].ch[1]
    #define lself tree[tree[k].fa].ch[0]
    #define rself tree[tree[k].fa].ch[1]
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,q,fa[N],fa2[N],size[N];
    struct data{int ch[2],fa,rev;
    }tree[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);}
    void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;}
    void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
    int whichson(int k){return rself==k;}
    bool isroot(int k){return lself!=k&&rself!=k;}
    void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
    void move(int k)
    {
        int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
        if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
        tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
        tree[k].ch[!p]=fa,tree[fa].fa=k;
    }
    void splay(int k)
    {
        push(k);
        while (!isroot(k))
        {
            int fa=tree[k].fa;
            if (!isroot(fa)) 
                if (whichson(fa)^whichson(k)) move(k);
                else move(fa);
            move(k);
        }
    }
    void access(int k){for (int t=0;k;t=k,k=tree[k].fa=find(tree[k].fa)) splay(k),tree[k].ch[1]=t;}
    void makeroot(int k){access(k),splay(k),rev(k);}
    void link(int x,int y){makeroot(x),tree[x].fa=y,fa2[find2(x)]=find2(y);}
    void dfs(int k,int x)
    {
        if (!k) return;
        if (find(k)!=x) size[x]+=size[find(k)],fa[find(k)]=x;
        dfs(lson,x),dfs(rson,x);
    }
    void addedge(int x,int y)
    {
        if (find2(x)!=find2(y)) link(x,y);
        else
        {
            makeroot(x),access(y),splay(y);
            dfs(tree[y].ch[0],y);tree[y].ch[0]=0;
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4998.in","r",stdin);
        freopen("bzoj4998.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),q=read();
        for (int i=1;i<=n;i++) fa[i]=i,fa2[i]=i,size[i]=1;
        for (int i=1;i<=m;i++)
        {
            int x=find(read()),y=find(read());
            if (x!=y) addedge(x,y);
        }
        for (int i=1;i<=q;i++)
        {
            int x=find(read()),y=find(read());
            if (x!=y) addedge(x,y);
            if (find(x)==find(y)) printf("%d
    ",size[fa[x]]);
            else printf("No
    "); 
        }
        return 0;
    }
  • 相关阅读:
    使用kendynet构建异步redis访问服务
    使用kendynet编写网关服务
    作为前端,我为什么选择 Angular 2?
    你必须知道的Javascript 系列
    JS日期(Date)处理函数总结
    JS数组(Array)处理函数总结
    消息推送之APNS
    消息推送之GCM
    Linux常用命令大全
    Sequential Container
  • 原文地址:https://www.cnblogs.com/Gloid/p/10056499.html
Copyright © 2011-2022 走看看