树上分治

1. 点分治

现在有一棵大小为 \(n\) 的树,要求出路径长度小于 \(k\) 的路径。

每次可以通过选择重心的方式,将整棵树分为一堆不大于 \(\dfrac{n}{2}\) 的子树,所以将整棵树分为大小为 \(1\) 的子树需要 \(\log n\) 次。

对于现在求出重心的子树,显然有三种情况可以组成一条路径。

  1. 路径两端点均在某一子树内
  2. 路径两端点在不同子树内
  3. 路径某一端点为重心

首先需要找出重心。

显然这个点不一定要是重心,只需要满足每个子树的大小不超过 \(\dfrac{n}{2}\) 即可。

记录每个点最大子树的大小即可,然后比较是否满足小于 \(\dfrac{n}{2}\)

然后处理出每个子树到其子树内的距离。

最后用双指针扫一下每个子树里满足条件的路径有多少,用容斥显然就是总的数量减去每个子树中的数量。

代码实现:


posted @ 2022-07-25 22:21  yzh_Error404  阅读(27)  评论(0)    收藏  举报