首页 > 代码库 > 【BZOJ】2049 [Sdoi2008]Cave 洞穴勘测

【BZOJ】2049 [Sdoi2008]Cave 洞穴勘测

【算法】Link-Cut Tree

【题解】lct

不是很懂你们会压常数的>_<!

技术分享
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10010;
int f[maxn],t[maxn][2],n,m;
bool g[maxn];
bool isroot(int x)
{return (t[f[x]][0]!=x&&t[f[x]][1]!=x);}
void pushdown(int x)
{
    if(g[x])
    {
        swap(t[x][0],t[x][1]);
        g[t[x][0]]^=1;g[t[x][1]]^=1;
        g[x]=0;
    }
}
void rotate(int x)
{
    int k=x==t[f[x]][1];
    int y=f[x];
    t[y][k]=t[x][!k];f[t[x][!k]]=y;
    if(!isroot(y))t[f[y]][y==t[f[y]][1]]=x;f[x]=f[y];f[y]=x;
    t[x][!k]=y;
}
int N[maxn];
void splay(int x)
{
    int tot=0;
    int y=x;//此处不能直接上移x,因为待会还要用。 
    while(!isroot(y))N[++tot]=y,y=f[y];
    pushdown(y);
    for(int i=tot;i>=1;i--)pushdown(N[i]);
    while(!isroot(x))
    {
        if(isroot(f[x])){rotate(x);return;}
        int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1];
        if(X^Y)rotate(x),rotate(x);
         else rotate(f[x]),rotate(x);
    }
}
void access(int x)
{
        int y=0;
        while(x)
        {
            splay(x);
            t[x][1]=y;
            y=x;x=f[x];
        }
}

void reserve(int x)
{access(x);splay(x);g[x]^=1;}

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

void cut(int x,int y)
{reserve(x);access(y);splay(y);t[y][0]=f[x]=0;}

int ask_root(int x)
{
    access(x);splay(x);
    while(t[x][0])x=t[x][0];
    return x;
}
void find_root(int x,int y)
{
    if(ask_root(x)==ask_root(y))printf("Yes\n");else printf("No\n");
}
char s[20];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%s%d%d",s+1,&x,&y);
        if(s[1]==C)link(x,y);
        if(s[1]==D)cut(x,y);
        if(s[1]==Q)find_root(x,y);
    }
    return 0;
}
View Code

 

【BZOJ】2049 [Sdoi2008]Cave 洞穴勘测