树分治总结

来源:互联网 发布:优酷淘宝搞笑视频 编辑:程序博客网 时间:2024/05/21 11:07

一.前言

树分治就是在树形结构上进行分而治之的操作,包括点分治和边分治。

①点分治的效率比较稳定,最坏情况下递归深度为O(logn)。

②边分治在定点度数D为常数时,基于边的分治递归最坏深度为O(log N) ,然而D较大时会达到O(N),这种效率显然是不行的,不过可以通过添加虚点,使得每个节点的度数都不大于3,这样既可保证效率。


二.点分治

例题:POJ-1741

题意:一棵有n个节点的树,每条边有个权值代表相邻2个点的距离,要求求出所有距离不超过k的点对(u,v)

点分治算法的过程:

1)找出树的重心

①计算以u为根的树中每棵子树的大小

②根据子树大小找出树的重心root(以树的重心为根的树,可以使其根的子树中节点最多的子树的节点最少)

2)将树的重心作为根节点root,计算树中每个点到root的距离dir

3)计算树中所有满足dir[u]+dir[v]<=k的点对数cnt1

4)计算以root的子节点为根的子树中,满足dir[u]+dir[v]<=k的点对数cnt2

5)ans+=cnt1-cnt2

6)删掉节点root,分别遍历root的子树,回到第1)步

题解链接:POJ-1741


三.边分治

边分治的主要过程:

首先为了保证效率(边分治递归深度是由点的度数决定的),要添加虚点用来“平衡”节点的度数,重建树的算法以后再补上。

边分治就是选在当前分治结构里面选一条边,使得边的两端最大子树尽可能的小,这样的边我们称作中心边不同于点分治的是,中心边只会把树分成2个子树,因此处理起来比较方便,找中心边的方法和找重心的方法一样,都是要找使最大子树尽可能小的那一条边。

对于一个分治结构,假设找到的中心边为x-y,对于这个分治结构中的路径只有两种:不经过边x-y的和经过边x-y的,前者由子分治结构来考虑,现在只考虑后者。处理完当前子树后,删掉中心边,将子树分成2个联通块,再进行递归操作。


例题:SPOJ-QTREE4

题意:

给定一棵树,节点有黑白两种颜色,有正负的边权。有两种操作:

①修改反转某个节点的颜色;

②询问树上最远的两个白色节点的距离。


边分治算法的过程:

1)添加虚点,使每个点的度数不超过3,虚点的颜色定为黑色(不对查询有影响)

2)每层选中一条中心边(找中心边方法同找重心方法)

3)删掉中心边,可以分成左右两个子树

4)左右子树各维护一个单调队列,分别记录白点到子树根的距离

5)对于每个白点,记录自己在哪几个队列中(修改时要用)

6)ans=max{左子树的ans,右子树的ans,左子树的最远距离+右子树的最远距离+中心边长度}

7)递归遍历左右子树,回到第2)步

8)修改操作:

①白色->黑色:把包含u的所有根节点的队列进行更新(弹出黑色节点),并更新ans

②黑色->白色,将u放入包含u的根节点的队列中,并更新ans

题解链接:SPOJ-QTREE4

原创粉丝点击