对于要求我们统计树上符合条件的路径信息的问题,我们一般可以采用两种方法来实现,一种是树上DP,一种就是点分治。点分治更加的简洁暴力,而树上DP往往会带来相当复杂的状态转移方程,甚至我们无法推出状态转移方程。
点分治的核心思想就是枚举每一个顶点并统计经过该顶点的所有路径信息,而这一过程是通过重构树来实现的,并且要令重构的树拥有尽可能小的深度以获得更优的性能,换言之,尽可能平衡。由于树是双向无环连通图,对于图中的任意顶点,我们均可以将其作为树根,从而将图转换为一株树。那么应该选择哪个结点呢?我们选择树的重心作为根结点。所谓的树的重心就是指这样的一个结点x,所有与其直接相连的子树的大小(其内包含的结点数目)均不超过整株树大小的1/2,很显然一株树可能存在多个重心,比如只有两个结点的时候,两个结点均可以作为重心。
而对于点分治,我们接受一株树,并负责从中找到树的重心,处理所有经过重心的路径,之后将重心从树中移除,此时树散落为多株规模更小的树,为这些树递归调用点分治的流程,这样我们就处理了所有可能的路径(因为一条路径必然至少经过一个顶点,而对于任意顶点,我们都处理了经过它的路径,所以我们处理了所有的路径)。由于寻找重心和处理经过重心的路径这一任务的时间复杂度为线性的,即如果树的大小为m,则时间复杂度为O(m)。而每一层次的递归调用,所涉及的所有子树的大小和始终不超过O(n),n为原始图的大小,因此每一层次的时间复杂度均为O(n),最终的时间复杂度如分治算法一样取决于递归的层次。而由于移除重心后,所有的子树大小最大为原来的一半,而递归终止于树的大小为1的时候,因此递归的层次可以很容易得出不超过log2(n),总的时间复杂度对应的为O(nlog2(n))。
下面说一下重心的其它性质:
性质1:如果一个结点是树的重心,则其下最大的子树的大小必然最小。
证明:假设x是一个含n个结点的树的重心,对于任意不同于x的结点y。我们发现y必然存在与x下的某株以z为根的子树中,而这意味着当以y为根结点时,以x为根的子树的大小T'(x)为整株树的大小n减去以z为根的子树大小|T(z)|,而由于x是重心,故T(z)<=n/2,故T'(x)>=n/2,即y的最大子树的大小至少为T'(x)=n/2,因此x的最大的子树的大小必然最小。
性质2:如果一株含n个结点的树有多个重心,则每个重心的最大子树的大小均为n/2。
证明:由性质1的证明可以直接得出。
性质3:设树含n个结点,若u是树的重心,而v是不同于u的树上的结点,那么向以v为根的子树中追加新的结点,树的重心将沿着从u到v的简单路径移动最多一个结点。
证明:追加一个结点后,树的大小变成了n+1,如果u的所有子树大小依旧保证小于(n+1)/2,那么u将始终是树的重心。否则,若u的某个子树大小超过了(n+1)/2,那么肯定是由包含v的子树的大小增大导致的,而且很容易发现这株子树在没有扩增前的大小应该为n/2。我们将重心从u向v移动一个单位后,此时其所有的子树大小均保证不超过(n+1)/2(此时T'(u)=n-n/2<=(n+1)/2)。
性质4:将两株分别以a与b为重心的树A、B通过一条边(u,v)连接起来,那么新的重心必然处于a到b的简单路径上。
证明:不妨设新的重心落在A上,那么这等价于向A中结点u所代表的子树上不断追加新的结点,由性质3可以保证A的重心不断沿着A与结点u之间的路径不断移动。而前提已经说明了重心始终落在A上,因此新的重心必然落在A与u之间。而对应的如果新的重心落在B上,那么新的重心必然处于B与v的简单路径上,无论哪种情况,都能保证新的重心一定处于a与b的路径上。
性质5:一株树的重心必然存在。
证明:当树的大小为1时,显然成立,而建立一株树的过程可以表示为向原本只有一个结点的树追加新的结点,利用性质3提到的算法,沿着某条路径移动最多一个结点,即可得到新的重心。而但所有顶点加入完成后,重心也得以确认。
性质6:一株树最多有两个重心。
证明:考虑有三个重心的情况,其中至少有两个重心是之间是没有边的。记这两个重心为a、b。由性质2知道a和b的最大子树的大小都是n/2。考虑以b为根,这时候以a为根的子树大小必定小于n/2,同理,以a为根时,以b为根的子树大小页一定小于n/2。故当我们从a出发沿着b前进时,在第一步的情况下,最大子树会保持不变,之后每一步,最大子树大小都会增加1,因此b不可能是重心。