bzoj2049[Sdoi2008]-Cave洞穴勘测

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2049

题目大意:有n个洞 m个操作 

操作有三种:

 Connect u v 联通u到v
 Destroy u v 断开u到v
 Query u v 询问u和v是否连通

题解:LCT的模版题*1

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 10100

struct LinkCutTree
{
	int fa[maxn];
	int son[maxn][2];
	int rev[maxn];
	void clear(int n)
	{
		for (int i=0;i<=n;i++) 
		 {rev[i]=son[i][0]=son[i][1]=fa[i]=0;}
	}
	bool Is_root(int x)
	{
		if (son[fa[x]][0]==x) return false;
		if (son[fa[x]][1]==x) return false;
		return true;
	}
	void Push_Down(int x)
	{
		if (rev[x])
		{
			int t=son[x][0];
			son[x][0]=son[x][1];
			son[x][1]=t;
			rev[son[x][0]]^=1;
			rev[son[x][1]]^=1;
			rev[x]=0;
		}
	}
	void Rotate(int x)
	{
		int y=fa[x],z=fa[y];
		int a=son[y][1]==x;
		int b=son[z][1]==y;
		if (!Is_root(y)) son[z][b]=x;
		if (son[x][1-a]!=0) fa[son[x][1-a]]=y;
		son[y][a]=son[x][1-a];
		son[x][1-a]=y;
		fa[y]=x;fa[x]=z;
	}
	int sta[maxn];
	void Pre(int x)
	{
		int tp=0;
		for (;!Is_root(x);x=fa[x]) sta[++tp]=x;
		sta[++tp]=x;
		while (tp>0) {Push_Down(sta[tp]);tp--;}
	}
	void Splay(int x)
	{
		Pre(x);
		while (!Is_root(x))
		{
			int y=fa[x],z=fa[y];
			if (!Is_root(y))
			{
				int a=son[y][1]==x;
				int b=son[z][1]==y;
				if (a==b) Rotate(y);
				else Rotate(x);
			}Rotate(x);
		}
	}
	void Access(int x)
	{
		int last=0;
		while (x!=0)
		{
			Splay(x);
			son[x][1]=last;
			last=x;
			x=fa[x];
		}
	}
	void Make_root(int x)
	{
		Access(x);
		Splay(x);
		rev[x]^=1;
	}
	void Split(int x,int y)
	{
		Make_root(x);
		Access(y);
		Splay(y);
	}
	int Find_root(int x)
	{
		Access(x);
		Splay(x);
		while (son[x][0]!=0) x=son[x][0];
		return x;
	}
	bool Connect(int x,int y)
	{
		if (Find_root(x)==Find_root(y)) return true;
		return false;
	}
	void Link(int x,int y)
	{
		if (Connect(x,y)) return;
		Make_root(x);
		fa[x]=y;
	}
	void Cut(int x,int y)
	{
		if (!Connect(x,y)) return;
		Split(x,y);
		if (son[y][0]!=x) return;
		fa[x]=0;
		son[y][0]=0;
	}
}lct;
int main()
{
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int n,m,i,u,v;char c[20];
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		lct.clear(n);
		for (i=1;i<=m;i++)
		{
			scanf("\n");
			scanf("%s%d%d",c,&u,&v);
			if (c[0]=='C') lct.Link(u,v);
			else if (c[0]=='D') lct.Cut(u,v);
			else if (c[0]=='Q')
			{
				if (lct.Connect(u,v)) printf("Yes\n");
				else printf("No\n");
			}
		}
	}
	return 0;
}
我会说这个模版我打了三次没有一次一A吗QAQ

posted @ 2016-08-26 16:14  OxQ  阅读(...)  评论(... 编辑 收藏