📌  相关文章
📜  不允许来自具有相邻级别的树的最大总和(1)

📅  最后修改于: 2023-12-03 15:35:54.273000             🧑  作者: Mango

不允许来自具有相邻级别的树的最大总和

当需要求解一棵树中不相邻节点之和的最大值时,我们可以采用动态规划的方法。对于每个节点,我们可以定义两个状态:

  • $dp[i][0]$:表示不选择第 $i$ 个节点能得到的最大价值;
  • $dp[i][1]$:表示选择第 $i$ 个节点能得到的最大价值。

针对这种问题,我们需要以某个根节点为起点递归进行求解,最后将所有结果求最大。具体步骤如下:

  1. 定义节点内的子节点 $son$ 和父节点 $fa$。
  2. 对于每个节点 $i$,我们可以分以下两种情况进行讨论:
  • 如果我们不选择第 $i$ 个节点,则可以选择其所有子节点,总价值为 $sum(son)$;此时,状态转移方程为:$dp[i][0] = \sum\limits_{j \in son}\max(dp[j][0],dp[j][1])$。
  • 如果我们选择第 $i$ 个节点,则不能选择其所有子节点,但可以选择其所有孙子节点,总价值为 $i$ 的价值加上 $\sum\limits_{j \in son}\max(dp[j][0],dp[j][1])$;此时,状态转移方程为:$dp[i][1] = val[i] +\sum\limits_{j \in son}\max(dp[j][0],dp[j][1])$。其中,$val[i]$ 表示节点 $i$ 的价值。
  1. 最终,所有节点的最大价值为 $\max(dp[i][0],dp[i][1])$($i$ 为根节点)。

下面是该算法的Python实现代码:

def dfs(u, fa):
    dp[u][0], dp[u][1] = 0, val[u]
    for v in tree[u]:
        if v == fa:
            continue
        dfs(v, u)
        dp[u][0] += max(dp[v][0], dp[v][1])
        dp[u][1] += dp[v][0]

n = int(input())
tree = [[] for i in range(n+1)]
dp, val = [[0] * 2 for i in range(n+1)], [0] * (n+1)

for i in range(1, n+1):
    val[i] = int(input())

for i in range(n-1):
    u, v = map(int, input().split())
    tree[u].append(v)
    tree[v].append(u)

dfs(1, 0)
print(max(dp[1][0], dp[1][1]))

该算法的时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。