●BZOJ 2049 [Sdoi2008]Cave洞穴勘测

题链:

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;
}

  

原文地址:https://www.cnblogs.com/zj75211/p/8365668.html