题链:
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 "):printf("No "); else if(s[0]=='C') DT.Link(x,y); else DT.Cut(x,y); } return 0; }