您的位置:首页 > 理论基础 > 数据结构算法

bzoj2049[洞穴勘测]纯粹的LCT

2016-03-10 10:49 621 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=2049

就像lct=link-cut-tree一样,这道题是纯粹的LCT.为什么呢,它的操作一共就只有link,cut.(query是查询)

可以说是非常的裸,但是对于我这个刚学的菜鸟还是有一个地方比较纠结

首先初始化所有的点,是他们各自是一棵树。

然后一旦两个点两边就link两个森林。

link操作是一样的,access(u),splay(u),u->rev=1,u->f=v.  思想不变

query操作 就分别找两棵树的splay上的根,判断是否相同

唯一纠结的就是cut操作,不清楚谁是谁的父亲

这说明我并没有弄清楚LCT的实质。

对于一棵splay,随便选哪棵做根都可以,于是我们考虑把u设为根(这棵树),然后access(v),得到u-v的路径,然后splay(v),v的左边一定是比u深度小的,而u-v直接相连并且u为整棵树的根,所以在splay中v作根,v的左儿子一定就是u了。

然后这道题就是模板题了:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=10000+5;
/*
洞穴勘测:标准的link-cut-tree
*/
int n,m;
struct node
{
node *f;
node *ch[2];
bool rev;
}tree[maxn],*null,Tnull;
void init(node *u)
{
u->f=u->ch[0]=u->ch[1]=null;
u->rev=0;
}
bool isroot(node *u)
{
return u==null||u->f->ch[0]!=u&&u->f->ch[1]!=u;
}
void pushdown(node *u)
{
if(u==null)return ;
if(u->rev)
{
swap(u->ch[0],u->ch[1]);
if(u->ch[0]!=null)u->ch[0]->rev^=1;
if(u->ch[1]!=null)u->ch[1]->rev^=1;
u->rev=0;
}
}
void rotate(node *u)
{
node *f=u->f;
node *ff=f->f;
int d=u==f->ch[1];

if(u->ch[d^1]!=null)u->ch[d^1]->f=f;
f->ch[d]=u->ch[d^1];

u->f=ff;
if(ff!=null)
{
if(f==ff->ch[0])ff->ch[0]=u;
else if(f==ff->ch[1])ff->ch[1]=u;
}

u->ch[d^1]=f;
f->f=u;
}
int cnt;
node *sta[maxn];
void splay(node *u)
{
if(u==null)return ;
cnt=1;
sta[0]=u;
for(node
4000
*y=u;!isroot(y);y=y->f)
{
sta[cnt++]=y->f;
}
while(cnt)pushdown(sta[--cnt]);
while(!isroot(u))
{
node *f=u->f;
if(isroot(f))
{
rotate(u);
}
else
{
node *ff=f->f;
int d=u==f->ch[1];
int dd=f==ff->ch[1];
if(d==dd)rotate(f);
else rotate(u);
rotate(u);
}
}
}
node *access(node *u)
{
node *v=null;
while(u!=null)
{
splay(u);
u->ch[1]=v;
v->f=u;
v=u;
u=u->f;
}
return v;
}
bool sam(node *u,node *v)
{
while(u->f!=null)u=u->f;
while(v->f!=null)v=v->f;
return u==v;
}
void link(node *u,node *v)
{
access(u);
splay(u);
u->rev=1;
u->f=v;
}
void changeroot(node *u)
{
access(u)->rev^=1;
}
void cut(node *u,node *v)
{
changeroot(u);
access(v);
splay(v);
v->ch[0]=v->ch[0]->f=null;
}
char ss[20];
int main()
{
null=&Tnull;
init(null);
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
init(&tree[i]);
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%s%d%d",ss,&u,&v);
if(ss[0]=='Q')
{
bool ok=sam(tree+u,tree+v);
if(ok)printf("Yes\n");
else printf("No\n");
}
else if(ss[0]=='C')
{
link(tree+u,tree+v);
}
else if(ss[0]=='D')
{
cut(tree+u,tree+v);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LCT 数据结构