树链剖分

来源:互联网 发布:淘宝banner图 编辑:程序博客网 时间:2024/05/16 20:30

一棵树可以剖分成好多的链

鬼都知道ヾノ≧∀≦)o死开!

树链剖分的方法可以将树固定地分为几个链
生成树
跑两遍图
第一遍维护子节点最多的重(zhong)儿子
由重儿子们组成了重链
第二遍维护出重儿子优先的dfs入栈序
这样这个入栈序就可以拆分成几个重链
如图
一棵树
这棵树上边权为1的边为重链,除叶子节点外,每个节点必有重儿子
若存在多个儿子子节点和相等,则任取一个作为重儿子
该树的序为
1246 5 378 9
每个空格隔开的区间都是一条重链
于是一棵树就这么被剖开了
挺简单易懂是不是
为了更快速遍历这些链
我们维护一个top数组
存储每个节点所在重链的深度最浅的点
在第二遍dfs时,可以顺便维护出来
于是我们就可以用一些神奇的数据结构迅速地维护这棵树
树链剖分还可以求lca
非常快O(log n) 即可出答案
过程大概是
每次优先维护二者中深度更深的top
维护从top到当前节点这个区间的值
直到二者top相同
此时二者必在同一链上
最后维护二者之间的区间即可
实现:

int lca(int x,int y){    while(top[x]!=top[y])    {        if(dep[top[x]]<dep[top[y]])//dep为深度            swap(x,y);//交换两个数        //此处可维护链,用一个映射存dfs序,如果需要再存一个反映射方便找回原数        x=fa[top[x]];    }    //此处也可维护链    retrun dep[x]<dep[y]?x:y;//返回深度较小的点}
0 0
原创粉丝点击