BZOJ 2049: [Sdoi2008]Cave 洞穴勘测【LCT】
2049: [Sdoi2008]Cave 洞穴勘测
【题目描述】
传送门
【题解】
裸地link Cut Tree。最近刚学,所以打了一些模板题。
代码如下
#include<cstdio>
#include<algorithm>
#define MAXN 10005
using namespace std;
struct Link_Cut_Tree{
int Top,Rtd[MAXN],Son[MAXN][2],Fa[MAXN],que[MAXN];
void PushDown(int x){
int &L=Son[x][0],&R=Son[x][1];
if(Rtd[x]){
Rtd[L]^=1;Rtd[R]^=1;Rtd[x]^=1;
swap(L,R);
}
}
int Get(int x){return Son[Fa[x]][1]==x;}
bool IsRoot(int x){return Son[Fa[x]][0]!=x&&Son[Fa[x]][1]!=x;}
void Rotate(int x){
int y=Fa[x],z=Fa[y],L,R;
R=(L=Get(x))^1;
if(!IsRoot(y)) Son[z][Son[z][1]==y]=x;
Fa[x]=z;Fa[y]=x;Fa[Son[x][R]]=y;
Son[y][L]=Son[x][R];Son[x][R]=y;
}
void Splay(int x){
que[Top=1]=x;
for(int i=x;!IsRoot(i);i=Fa[i]) que[++Top]=Fa[i];
for(int i=Top;i;i--) PushDown(que[i]);
while(!IsRoot(x)){
int y=Fa[x],z=Fa[y];
if(!IsRoot(y)) (Son[y][0]==x)^(Son[z][0]==y)?Rotate(x):Rotate(y);
Rotate(x);
}
}
void Access(int x){for(int t=0;x;t=x,x=Fa[x]) Splay(x),Son[x][1]=t;}
void MakeRoot(int x){Access(x);Splay(x);Rtd[x]^=1;}
int Fnd(int x){Access(x);Splay(x);while(Son[x][0]) x=Son[x][0];return x;}
void Split(int x,int y){MakeRoot(x);Access(y),Splay(y);}
void Cut(int x,int y){
Split(x,y);
if(Son[x][1]||Fa[x]!=y||Son[y][Get(x)^1]) return;
Fa[x]=Son[y][0]=0;
}
void Lnk(int x,int y){MakeRoot(x);Fa[x]=y;}
}Tre;
int n,m;
int main(){
#ifndef ONLINE_JUDGE
freopen("2049.in","r",stdin);
freopen("2049.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
char ch[10];int x,y;scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='C'){if(Tre.Fnd(x)!=Tre.Fnd(y)) Tre.Lnk(x,y);}else
if(ch[0]=='D'){if(Tre.Fnd(x)==Tre.Fnd(y)) Tre.Cut(x,y);}else
printf(Tre.Fnd(x)==Tre.Fnd(y)?"Yes\n":"No\n");
}
return 0;
}