点分治笔记
原文:来自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]\)。