P2147 [SDOI2008]洞穴勘测

//Pro:P2147 洞穴勘测


#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1e4+5;

int c[N][2],f[N];
bool rev[N];
int st[N],t;

inline bool get(int x)
{
    return c[f[x]][1]==x;
}

inline bool nroot(int x)
{
    return c[f[x]][0]==x||c[f[x]][1]==x;
}

inline void pushrev(int x)
{
    if(!rev[x])
        return;
    swap(c[x][0],c[x][1]);
    if(c[x][0])
        rev[c[x][0]]^=1;
    if(c[x][1])
        rev[c[x][1]]^=1;
    rev[x]=0;
}

inline void rotate(int x)
{
    int y=f[x],z=f[y],k=get(x),w=c[x][!k];
    if(z&&nroot(y))
        c[z][get(y)]=x;
    c[x][!k]=y,c[y][k]=w;
    if(w)
        f[w]=y;
    f[y]=x,f[x]=z;
}

inline void splay(int x)
{
    int y,z;
    st[t=1]=x;
    for(y=x;nroot(y);y=f[y])
        st[++t]=f[y];
    for(;t;--t)
        pushrev(st[t]);
    while(nroot(x))
    {
        y=f[x],z=f[y];
        if(nroot(y))
            rotate(get(x)^get(y)?x:y);
        rotate(x);
    }
}

inline void access(int x)
{
    for(int y=0;x;x=f[y=x])
        splay(x),c[x][1]=y;
}

inline void makeroot(int x)
{
    access(x),splay(x);
    rev[x]^=1;
}

inline int findroot(int x)
{
    access(x),splay(x);
    for(pushrev(x);c[x][0];pushrev(x))
        x=c[x][0];
    splay(x);
    return x;
}

inline void link(int x,int y)
{
    makeroot(x);
    f[x]=y;
}

inline void cut(int x,int y)
{
    makeroot(x);
    access(y),splay(y);
    c[y][0]=f[x]=0;
}

int n,m,a,b;
char opt[10];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        scanf("%s",opt);
        scanf("%d%d",&a,&b);
        if(opt[0]=='Q')
        {
            if(findroot(a)==findroot(b))
                puts("Yes");
            else
                puts("No");
        }
        else if(opt[0]=='C')
            link(a,b);
        else
            cut(a,b);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lovewhy/p/9633856.html