MaximumBinaryTreeRadiusSum 最大二叉树和

问题

一个二叉树共有nn个节点,范围为[1,n][1,n],每个节点拥有一个权值,所有节点的权值之和不超过mm。从任意节点ii都可以到达另一节点jj,且路线是唯一的,每一条的距离为1(节点与自己的距离为0,与其父节点、左右孩子节点的距离为1)。设节点ii权值为viv_{i},所有到节点ii的距离小于等于radiusradius的节点权值之和为p=1nivp\sum_{p=1}^{n_{i}} v_{p} 。称该权值之和为节点ii在半径radiusradius上的半径和。下图演示了节点44覆盖到的半径为22的区域:

求二叉树的最大半径和。

解法

根据上图我们可以看出,找出节点ii半径radiusradius内的所有节点并求和,即可得到该节点的半径和。二叉树中沿着父节点向上移动,和沿着左右孩子向下移动的操作不一样,因此将其区分。设f(i,j)f(i,j)表示节点ii在半径为jj的范围内,只沿着父节点向上移动的半径和,则有状态转移方程:

f(i,j)={0(initialize)i[1,n],j=0f(fatheri,j1)+vi(loop)i,fatheri[1,n],0j1<jmf(i,j) = \begin{cases} 0 & (initialize) & i \in [1,n], j = 0 \\ f(father_{i}, j-1) + v_{i} & (loop) & i, father_{i} \in [1,n], 0 \leq j-1 \lt j \leq m \end{cases}

(1)(1) 初始化,向上半径为00时节点ii的半径和为00,即g(i,0)=0g(i,0) = 0

(2)(2) 节点ii在半径jj上向上的半径和,显然等于它的父结点fatherifather_{i}在半径为j1j-1上的半径和与它自己的权值之和,即f(i,j)=f(fatheri,j1)+vif(i,j) = f(father_{i}, j-1) + v_{i}

下图演示节点77向上半径为33所覆盖到的节点:

g(i,j)g(i,j)表示节点ii在半径jj的范围内,只沿着左右孩子节点向下移动的半径和,则有状态转移方程:

g(i,j)={0(initialize)i[1,n],j=0g(lefti,j1)+g(righti,j1)+vi(loop)i,lefti,righti[1,n],0j1<jmg(i,j) = \begin{cases} 0 & (initialize) & i \in [1,n], j = 0 \\ g(left_{i}, j-1) + g(right_{i}, j-1) + v_{i} & (loop) & i, left_{i}, right_{i} \in [1,n], 0 \leq j-1 \lt j \leq m \end{cases}

(1)(1) 初始化,向下半径为00时节点ii的半径和为00,即g(i,0)=0g(i,0) = 0

(2)(2) 节点ii在半径jj上向下的半径和,显然等于它的左右孩子节点lefti,rightileft_{i}, right_{i}在半径为j1j-1上的半径和与它自己的权值之和,即g(i,j)=g(lefti,j1)+g(righti,j1)+vig(i,j) = g(left_{i}, j-1) + g(right_{i}, j-1) + v_{i}

下图演示节点11向下半径为33所覆盖到的节点:

还漏掉了节点ii的叔叔节点uncleiuncle_{i},下图演示节点44在半径22上覆盖到的所有节点,其中没有被f(4,2)f(4,2)g(4,2)g(4,2)覆盖到的节点用绿色标记:

h(i,j)h(i,j)为节点ii在半径jj上的半径和(本问题所求),则有状态转移方程:

h(i,j)={0(initialize)i[1,n],j=0f(fatheri,j1)+g(unclei,j2)+g(lefti,j1)+g(righti,j1)+vi(loop)i,fatheri,unclei,lefti,righti[1,n],0j2<j1<jmh(i,j) = \begin{cases} 0 & (initialize) & i \in [1,n], j = 0 \\ f(father_{i}, j-1) + g(uncle_{i}, j-2) + g(left_{i},j-1) + g(right_{i}, j-1) + v_{i} & (loop) & i, father_{i}, uncle_{i}, left_{i}, right_{i} \in [1,n], 0 \leq j-2 \lt j-1 \lt j \leq m \end{cases}

(1)(1) 初始化,半径为00时节点ii的半径和为00,即h(i,0)=0h(i,0) = 0

(2)(2) 节点ii在半径jj上的半径和,显然等于它的父节点、左右孩子节点在半径为j1j-1上的半径和,以及叔叔节点在半径为j2j-2上的半径和,与它自己的权值之和,即h(i,j)=f(fatheri,j1)+g(unclei,j2)+g(lefti,j1)+g(righti,j1)+vih(i,j) = f(father_{i}, j-1) + g(uncle_{i}, j-2) + g(left_{i}, j-1) + g(right_{i}, j-1) + v_{i}

遍历二叉树上所有节点,找出最大的半径和即可。该算法的时间复杂度为O(n×m)O(n \times m)

Cow Travelling

源码

MaximumBinaryTreeRadiusSum.h

MaximumBinaryTreeRadiusSum.cpp

测试

MaximumBinaryTreeRadiusSumTest.cpp

Last updated