树形DP-树的直径与重心

树的直径与重心

  • 直径
    • 定义
    • 树形DP解树的直径
    • 注意
  • 重心
    • 定义
    • 树形DP解树的重心

直径

定义

给定一颗树 T = ( V , E ) T=\left(V,E\right) T=(V,E) 直径为 m a x l e n ( u , v ) ( u , v ∈ V ) maxlen(u,v)(u,v\in V) maxlen(u,v)(u,vV)
树的直径普遍有两种求法,一个是两边 b f s / d f s bfs/dfs bfs/dfs另一个就是树形DP

树形DP解树的直径

树形DP-树的直径与重心_第1张图片
这颗树的直径很明显,就是 ( 8 , 14 ) (8,14) (8,14)
而如何用代码实现呢?

首先令:
f i , 1 f_{i,1} fi,1为点 i i i能到达的远的距离
f i , 2 f_{i,2} fi,2为点 i i i能到达的远的距离

f i , 1 = max ⁡ j ∈ i f j , 1 + l e n ( i , j ) f_{i,1}=\max_{j\in i}^{}{f_{j,1}+len(i,j)} fi,1=jimaxfj,1+len(i,j)
f i , 2 = max ⁡ k ∈ i   & &   k ≠ j f k , 1 + l e n ( i , k ) f_{i,2}=\max_{k\in i\ \&\&\ k\not=j }^{}{f_{k,1}+len(i,k)} fi,2=ki && k=jmaxfk,1+len(i,k)
m a x l e n = max ⁡ i ∈ V ( m a x l e n , f i , 1 + f i , 2 ) maxlen=\max_{i\in V}(maxlen,f_{i,1}+f_{i,2}) maxlen=iVmax(maxlen,fi,1+fi,2)
这样便实现了一遍遍历找出树的直径

注意

  1. f i , 1 , f i , 2 , m a x l e n ( i ∈ V ) f_{i,1},f_{i,2},maxlen(i\in V) fi,1,fi,2,maxlen(iV)的更新应该在遍历过后回溯时进行
  2. 直径不一定经过根
    例如 :树形DP-树的直径与重心_第2张图片
    的直径应该是 10 − 7 − 4 − 2 − 5 − 8 − 11 − 12 − 14 10-7-4-2-5-8-11-12-14 1074258111214并没有经过 ( 1 ) (1) (1)

重心

定义

找到一个点,其所有的子树中最大的子树节点数最少

树形DP解树的重心

令:
N N N为所有节点数
f i f_i fi i i i的子树的个数
m i m_i mi i i i的子树的节点数的最大值
则:
m i = max ⁡ j ∈ i f j m_i=\max_{j\in i}{f_j} mi=jimaxfj
f i = ∑ j ∈ i f j f_i=\sum_{j\in i}{f_j} fi=jifj
a n s = min ⁡ i ∈ V ( a n s , max ⁡ ( m i , N − f i ) ) ans=\min_{i\in V}(ans,\max(m_i,N-f_i)) ans=iVmin(ans,max(mi,Nfi))

你可能感兴趣的:(算法,c++)