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\n";
#else
    const char LL[]="%lld\n";
#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\n",size[fa[x]]);
        else printf("No\n"); 
    }
    return 0;
}

 

posted @ 2018-12-03 12:54  Gloid  阅读(227)  评论(0编辑  收藏  举报