[常见做法整合]CSP-S2019 D2T3 树的重心

Posted topsecret

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[常见做法整合]CSP-S2019 D2T3 树的重心相关的知识,希望对你有一定的参考价值。

CSP-S2019 D2T3 树的重心(centroid)

本题解是题解栏内一些常见思路的集合。

为了篇幅紧凑,在一些地方我可能跳过了证明/阐述的不是怎么详细,如果希望看到某一个思路的详细阐述/代码,可以点击相关的超链接。

思路

本题的部分分启发我们去找性质:

  1. 链的部分分启发我们去考虑树链剖分
  2. 二叉树的部分分启发我们去考虑以重心为根的情况。
  3. 由于要同时考虑子树与外子树的情况,这启发我们想到换根法

性质:

  1. 重心(u)在根节点所在的重链上。
  2. (uin son_{rt})(v)(u)的重心,则(rt)的重心为(v)的祖先。
  3. (u)为重心,只有(u)的重儿子(或父亲)有可能是重心。

计数方法:

  1. 对于每一个点,我们计算它作为重心的次数:这会导致实现偏向数据结构(BIT、可持久化线段树、树状数组等)。
  2. 对于每一个分割,我们去找两课树的重心:这回导致实现偏向图论类方法(树链剖分、找重儿子、倍增等)。

方法0:考虑点,只考虑定义

代码 类似思路的题解

考虑一个点(u),我们想要知道,它会成为几次重心。

将树在(u)处定根,设其最大的子树大小为(S=siz_w),则可以分为两种情况:

  1. 删去的边不在(tree_w)中,(tree_v otsubseteq tree_w):则(siz_vle n-2S)时,(u)成为重心。
  2. 删去的边在(tree_w)中:设除了(tree_w)最大的子树大小为(T),则(2S-nle siz_vle n-2T)(u)成为重心。

因此,我们考虑处理出以(u)为根,各个儿子的({siz})的可重集合的情况,再查询一段区间内的(siz)的个数即可。

维护方法

可以用可持久化线段树(可能可以线段树合并/将所有查询离线化)维护。

特别地,(fa_u)的情况,相当于(tree-anc_u-tree_u)({u}+anc_u-{rt})取反。(其中,(anc_u)表示(u)的所有祖先节点)

方法1:考虑点,以重心为根

我们先找到重心(rt),并以它作为根。这样和随意选根有什么区别呢?

性质:若(x e rt)为重心,则删去的边((u,v))一定不在(tree_x)内。

因此,对一个点(u e rt),他作为重心仅当删去了一条边((x,y)),且:((x,y))不在(tree_u)内,(n-2s_xle Sle n-2g_x)。(设树减少的大小为(S)

对于根的情况,可以另外(分成割去的边在重儿子子树内与不在重儿子子树内)判断。

可以用树状数组维护,具体见这篇题解

方法2:考虑边

考虑一种删边情况,我们需要快速求出,划分后的所有重心。

考虑如何求一棵树的重心:因为重心一定在根节点所在重链上,从根一直跳重儿子,直到找到最深的(v)使得,(2s_v > s_u),则(v)(可能还有它的重儿子)为重心。此过程可以用倍增加速。

由这种做法,我们可以在树链剖分,并预处理倍增数组之后(O(log n))地求出任何子树的重心。

高赞题解的变体

我们考虑一个划分((u,v)),不妨设(dep_u>dep_v)

考虑如何求(tree_u)的重心:我们从(u)出发,一直向重儿子跳,跳到找到重心(即,重儿子的子树大小不超过原树的一半)为止。

考虑如何求出(tree-tree_u)的重心:我们先将根换到(v)处(此时只改变了两个节点的关系),这样实际上就相当于求(tree_u)的重心!

具体实现在

方法3:考虑边,某神奇的(O(n))做法

就如之前所说的,可以在(O(n))计算出所有子树的重心,但是很难对去掉子树的部分找到一个重心单调移动的计算序列……

以重心为根,考虑删去的边在哪棵子树内:

  1. 不在重儿子的子树内:则枚举所有可能的子树大小,在根所在的重链上面走就好了。
  2. 在重儿子的子树内:
    1. 重儿子仍然为重儿子:此时,根仍然为重心。
    2. 次重儿子变为了重儿子:在次重儿子的重链上走即可。

这样就用纯图论方法完成了这题。

参考资料

以上是关于[常见做法整合]CSP-S2019 D2T3 树的重心的主要内容,如果未能解决你的问题,请参考以下文章

学术篇NOIP2017 d2t3 列队phalanx splay做法

csp-s模拟测试60

「CSP-S 2019」树上的数(树上推理)

2019.9.19 csp-s模拟测试47 反思总结

[CSP-S模拟测试]:联盟(搜索+树的直径)

[CSP-S模拟测试]:tree(DP)