动态树 bzoj2049
来源:互联网 发布:计算机专业除了编程 编辑:程序博客网 时间:2024/05/16 04:11
经过一个下午的折腾,经过四个小时的debug,我的LCT基本定型了。。。
为了加深理解大概写点。。。
本文地址:http://blog.csdn.net/u012457935/article/details/19015059
其实动态树是一类问题啊,这个问题包含了很多的分治,具体可以去fhq666看,不过我们大多树情况还是把LCT(link cut tree)称为动态树
好吧不废话了。。。
动态树:
是一种基于树上操作的数据结构,程序大概只有几k但是却可以实现许多操作。(写前最好有树链剖分的基础)
实际上这种数据结构与树链剖分有异曲同工之处,都是化树为链,只不过树链剖分是在线段树上实现的,而动态树是在splay上的实现的。
当然,可以理解为动态树是熟料剖分的拓展,从功能上可以看出来。。
还有一个重点就是动态树所维护的树是可以动的(废话。。。。)这就导致树链剖分中的轻重边定义失效了,所以动态树上的轻重边的定义是基于操作的,不过这并不重要,原来在树链剖分中的各种定理也是可以用的。。要是不能用...........你就别用了。
这大概就是动态树的基础知识。。。个人认为已经比较详细了。。
动态树的基本操作:
首先是最基础的access操作:
即将当前节点到root上的所有边都变为重边
其他是一些基本的操作:
build_tree
很简单啊就是每个点一棵树(请自行区分本文中的树是指splay还是题中的树)
evert
将当前节点x到当前根节点的所有树边都反向,经过这样的一次操作以后根就是当前节点了。。
cut
将节点x与其树中的边删去
link
使得节点y成为x的孩子
find
找到当前节点x在树中的根节点。
下面将一些具体实现的东西:
①access(x)
首先如果当前节点x与root在一棵树中,那么直接解决问题了就
否则设u为x所在树的path_parent,那么将u通过splay操作转到根,然后用x所在的树代替u的右子树。同时将原来u的右子树w的path_parent设为x
②find(x)
首先对当前节点access(我说是基础吧。。。)然后你懂得
③evert(x)
这个操作的正经定义应该是是节点x成为当前树的根
不过这等价于x到root的边都取反
首先还是access,然后在平衡树上取反嘛。。。。正常操作是o(n)的。。。。
不过我们可以借鉴线段树上的标记操作,同样给节点打上res操作,这样就可以了!不过一定要及时正确的使用down函数进行标记的下放,要不然多放了会tle,少放了会wa
④link(x,y)
为了保证合并后的树是合法的,我们首先要使x成为其所在树的根节点,同时将x splay到根,此时x的左子树是空的(废话。。。。)我们此时就可以把y也splay到他所在树的根然后连到x的左子树上。
好机智!
⑤cut(x,y)
首先将x置为根,在对y进行access,那么这个时候xy就在一棵平衡树中了,这个时候我们只需要分离x和他的左子树目的就达成了。。。
这些就是基本的操作了。。如果有什么更神的操作再说。。。
---------------------------------------------------------by-----------------wbysr-------------------------------------------------------------------------------------------------------------------------------------------------
下面是例题bzoj2049的代码,这是个模板题,建议自己写写。
#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<algorithm>#define MAX 10010using namespace std;int n,m;struct anode{int id,father,path_parent,res;int child[2];};struct LinkCutTree{anode node[MAX];int cnt,location[MAX];void build(int x){int p=++cnt;location[x]=p;node[p].father=node[p].child[0]=node[p].child[1]=node[p].res=0;node[p].id=x;}void down(int x){if(!node[x].res)return;node[x].res=0;node[node[x].child[0]].res^=1;node[node[x].child[1]].res^=1;swap(node[x].child[0],node[x].child[1]);}void rotate(int p){int q=node[p].father,y=node[q].father,x=(node[q].child[1]==p);down(q);down(p);node[node[q].child[x]=node[p].child[x^1]].father=q;node[node[p].child[x^1]=q].father=p;node[p].father=y;node[p].path_parent=node[q].path_parent;node[q].path_parent=0;if(y)node[y].child[node[y].child[1]==q]=p;return;}void splay(int x,int aim=0){while(node[x].father){int fa=node[x].father;down(fa);if(node[fa].child[0])down(node[fa].child[0]);if(node[fa].child[1])down(node[fa].child[1]);rotate(x);}}void access(int x){splay(x);down(x);int y=node[x].child[1];node[x].child[1]=node[y].father=0;node[y].path_parent=x;for(y=node[x].path_parent;y;y=node[x].path_parent){splay(y);down(y);int r=node[y].child[1];node[r].father=0;node[r].path_parent=y;node[y].child[1]=x;node[x].father=y;node[x].path_parent=0;x=y;}splay(x);}void cut(int x,int y){evert(x);access(y);splay(y);down(y);node[node[y].child[0]].father=0;node[y].child[0]=0;}int find(int x){access(x);splay(x);down(x);while(node[x].child[0])x=node[x].child[0];//printf("xxx %d\n",x);splay(x);return x;}int get_root(int x){return node[find(x)].id;}void evert(int x)//使x成为所在树的根节点{access(x);splay(x);node[x].res^=1;down(x);}void link(int x,int y)//使x成为y的子节点{evert(x);splay(x);down(x);access(y);splay(y);down(y);node[x].child[0]=y;node[y].father=x;}void add(int x,int y){link(location[x],location[y]);}void destory(int x,int y){cut(location[x],location[y]);}}wbysr;int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)wbysr.build(i);while(m--){char ss[300];int u,v;scanf("%s",ss);scanf("%d%d",&u,&v);if(ss[0]=='C'){wbysr.add(u,v);}elseif(ss[0]=='D')wbysr.destory(u,v);else{int x=wbysr.get_root(u);int y=wbysr.get_root(v);if(x==y)printf("Yes\n");elseprintf("No\n");}}return 0;}
- 动态树 bzoj2049
- Review-动态树(Bzoj2049)
- [BZOJ2049]Cave 洞穴勘测 && 动态树
- 【动态树】[BZOJ2049] Cave 洞穴勘测
- 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 动态树
- [BZOJ2049][SDOI2008]洞穴勘测(动态树LCT)
- bzoj2049
- bzoj2049 LCT
- BZOJ2049 LCT
- LCT(模板题)BZOJ2049
- bzoj2049 洞穴勘测 lct
- BZOJ2049 洞穴勘测 LCT
- [BZOJ2049] [SDOI2008] 洞穴勘测
- bzoj2049(lct)
- 【bzoj2049】【LCT】洞穴勘测
- 【SDOI2008】bzoj2049 洞穴勘测
- bzoj2049 [ SDOI2008 ] -- LCT
- bzoj2049 Cave 洞穴勘测
- linux中tomcat启动错误:java.net.BindException: Permission denied <null>:80
- java io ---文件读取为byte数组
- ubuntu 11.04 中安装 opencv 2.3
- 面向对象基础知识(1)- 初步认识
- IOCP模型与网络编程
- 动态树 bzoj2049
- Windows下Android开发环境搭建和配置
- 九度oj 题目1030:毕业bg
- Ubuntu10.10下QTEmbedded-4.5.2在DM6446环境下的搭建
- 算法设计 技巧
- 第一章:左旋转字符串
- hbase查询一条数据的过程(转)
- CreateThread与pthread_create参数比较
- Windows环境下Android NDK环境搭建