题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=2049
题解:
LCT入门题
就是判两个点是否在同一颗树里
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10050
using namespace std;
int N,M;
struct LCT{
int ch[MAXN][2],fa[MAXN],rev[MAXN];
bool Which(int x){return ch[fa[x]][1]==x;}
bool Isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void Reverse(int x){rev[x]^=1;swap(ch[x][0],ch[x][1]);}
void Pushdown(int x){
if(!Isroot(x)) Pushdown(fa[x]);
if(rev[x]) rev[x]^=1,Reverse(ch[x][0]),Reverse(ch[x][1]);
}
void Rotate(int x){
static int y,z,l1,l2;
y=fa[x]; z=fa[y];
l1=Which(x); l2=Which(y); fa[x]=z;
if(!Isroot(y)) ch[z][l2]=x;
fa[ch[x][l1^1]]=y; fa[y]=x;
ch[y][l1]=ch[x][l1^1]; ch[x][l1^1]=y;
}
void Splay(int x){
static int y; Pushdown(x);
for(;y=fa[x],!Isroot(x);Rotate(x))
if(!Isroot(y)) Rotate(Which(x)==Which(y)?y:x);
}
void Access(int x){
static int y;
for(y=0;x;y=x,x=fa[x])
Splay(x),ch[x][1]=y;//Pushup
}
void Beroot(int x){
Access(x); Splay(x); Reverse(x);
}
void Cut(int x,int y){
Beroot(x); Access(y); Splay(y);
fa[x]=ch[y][0]=0; //Pushup(y)!
}
void Link(int x,int y){
Beroot(x); fa[x]=y;
}
int Findfa(int x){
Access(x); Splay(x);
while(ch[x][0]) x=ch[x][0];
return x;
}
bool Query(int x,int y){
return Findfa(x)==Findfa(y);
}
}DT;
int main(){
char s[10];
scanf("%d%d",&N,&M);
for(int i=1,x,y;i<=M;i++){
scanf("%s%d%d",s,&x,&y);
if(s[0]=='Q') DT.Query(x,y)?printf("Yes\n"):printf("No\n");
else if(s[0]=='C') DT.Link(x,y);
else DT.Cut(x,y);
}
return 0;
}