点分治笔记

原文:来自Grary
Download

分治算法在树的路径问题中的应用



关键字 : 树 路径 路径剖分 分治 数据结构

基于点的分治

首先选取一个点,将无根树转化为有根树,然后递归处理以根的儿子为根的子树。
基于边的分治
在树中选取一条边,将原树分成两棵不相交的树,递归处理。

效率分析

首先我们考虑如何选取点(边)。对于基于点的分治,我们选取一个点,要求将其删去后,结点最多的树的结点个数最小,这个点被称为“树的重心”。而基于边的分治,我们选取的边要满足所分离出来的两棵子树的结点个数尽量平均,这条边称为“中心边1”。

而对于这两个问题,都可以使用在树上的动态规划来解决,时间复杂度均为O(N),其中N为树的结点总数。对于树的分治算法来说,递归的深度往往决定着算法效率的高低,下面我们来分析上述两种方式的最坏递归深度。

定理 1:存在一个点使得分出的子树的结点个数均不大于\(\frac{N}{2}\)
证明:假设U是树的重心,它与\(V_1,V_2,\cdots ,V_k\)相邻,记\(Size(X)\)表示以X为根的子树的结点个数。记V为\(V_1-V_k\)中Size值最大的点。我们采取反证法,即假设\(Size(V)>\frac{N}{2}\)
那么我们考虑如果选取V作为根结点的情况,记Size'(X)表示此时以X为根的子树的结点个数。
如下图,对于A部分,显然
\(Size'(Ti)<Size(V)\),对于 B 部分,\(Size' (U) = N -Size(V) < N/2<Size(V)\),这与我们假设矛盾。
定理得证。

由定理 1 可得,在基于点的分治中每次我们都会将树的结点个数减少一半,因此递归深度最坏是\(O(log N)\)的,在树是一条链的时候达到上界。
定理 2:如果一棵树中每个点的度均不大于D,那么存在一条边使得分出的两棵子树的结点个数在\([N /(D+1),N*D/(D+1)].(N\leq 2)\)


例题一 POJ 1741 树上点对统计

给定一棵\(N(1\leq N \leq 10000)\)个结点的带权树,定义dist(u,v)为u,v两点间的最短路径长度,路径的长度定义为路径上所有边的权和。再给定一个K,如果对于不同的两个结点a,b,如果满足\(dist(a,b)\leq K\),则称(a,b)为合法点对。
求合法点对个数。

算法分析

如果使用普通的DFS遍历,时间复杂度高达\(O(N^2)\),而使用时间复杂度为O(NK)的动态规划,更是无法在规定时限内出解的。
我们知道一条路径要么过根结点,要么在一棵子树中,这启发了我们可以使用分治算法。路径在子树中的情况只需递归处理即可,下面我们来分析如何处理路径过根结点的情况。

路径在子树中的情况只需递归处理即可,下面我们来分析如何处理路径过根结点的情况。

\(Depth(i)\)表示点i到根节点的路径长度,Belong(i)=x(x为根节点的儿子),那么我们要统计的就是满足

  • \(Depth(i)+Depth(j)\leq K\)并且\(Belong(i)\not = Belong (j)\)\((i,j)\)个数
  • \(Depth(i)+Depth(j)\leq K\)并且\(Belong(i)=Belong(j)\)\((i,j)\)个数

将A排序后利用单调性容易得出一个\(O(n)\)的算法,所以可以用\(O(N\log N)\)的时间来解决这个问题.

综上,此题使用树的分治算法时间复杂度为\(O(N\log^2N)\)

例题2 SPOJ 1825 Free Tour 2

给定一棵含有\(N\)个节点的带权树,节点分为两类,黑点和白点。
要求找到一条路径,使得经过的黑点数目不超过\(K\)个,且路径长度最大。

算法分析

考虑此题维护树的路径,考虑使用树的分治来解决。
与上题相同,只需考虑过根节点的路径,其余的递归处理即可。
\(G(i,j)\)表示从根的第\(i\)个儿子到其子树中某点的最优路径的长度,要求此路径上的黑点不超过\(j\)个。
\(Dep(i,j)\)表示根节点的第\(i\)个儿子到其子树上的点的路径上最多的黑点个数。
那么当\(j>Dep(i)\)时,\(G(i,j)\)=G(i,Dep(i)),所以只需保留\(j\leq Dep(i)\)的部分,
这样就可以在\(O(N)\)的时间内算出\(G\),
那么我们最终需要求出\(Max(G(u,L_1)+G(v,L_2))\),其中\(u\not =v\),且\(L_1+L_2=K-[Root=Block]\)

转载于:https://www.cnblogs.com/qdscwyy/p/8177788.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值