bzoj2049 [Sdoi2008]Cave 洞穴勘测 [LCT]

题意:给你一颗树,n个节点m个询问,询问包含

①加一条边

②摧毁一条边

③询问X,Y是否连通。

题解:LCT模板题,link加边,cut删边,询问的时候先make_root(u),然后access(v),这时候若u和v在一棵树上,则在同一颗splay中。

AC代码:

#include  
#include  
#define N 20005 
using namespace std;  
//struct stp{int x,y,a,b;}a[N];  
//bool cmp(stp a,stp b){return a.aV[mx[x]])mx[x]=mx[ch[x][0]];  
    if(V[mx[ch[x][1]]]>V[mx[x]])mx[x]=mx[ch[x][1]];  
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;  
}  
void rotate(int x)  
{  
    int y=pre[x],z=pre[y];  
    bool f=ch[y][1]==x;  
    if(!is_root(y))ch[z][ch[z][1]==y]=x;  
    ch[y][f]=ch[x][!f];ch[x][!f]=y;  
    pre[x]=z;pre[y]=x;pre[ch[y][f]]=y;  
    update(y);update(x);  
}  
void splay(int x)  
{  
    st[t=1]=x;  
    for(int y=x;!is_root(y);st[++t]=y=pre[y]);  
    for(;t;t--)if(rev[st[t]])reverse(st[t]);  
    for(;!is_root(x);rotate(x))if(!is_root(pre[x]))  
        ch[pre[x]][0]==x^ch[pre[pre[x]]][0]==pre[x]?rotate(x):rotate(pre[x]);  
    update(x);  
}  
void access(int x){for(int t=0;x;ch[x][1]=t,t=x,x=pre[x])splay(x);}  
void make_root(int x){access(x);splay(x);rev[x]^=1;}  
void link(int x,int y){make_root(x);make_root(y);pre[x]=y;}//将x的父亲设为y   
void cut(int x,int y){make_root(x);access(y);splay(y);pre[x]=ch[y][0]=0;}  
bool find(int u,int v)
{	
	if(u==0)return 0;
	if(u==v)return 1;
	int ans=0;
	ans+=find(ch[u][0],v);
	ans+=find(ch[u][1],v);
	return ans;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	while(m--)
	{
		char op[25];
		int u,v;
		scanf("%s%d%d",op,&u,&v);
		if(op[0]=='C')link(u,v);
		else if(op[0]=='D')cut(u,v);
		else 
		{
			make_root(u);
			access(v);
			splay(v);
			if(find(v,u))printf("Yes\n");
			else printf("No\n");
		}
	}
}

 

 

 

你可能感兴趣的:(BZOJ,LCT,LCT,BZOJ)