PrepStack · Markdown HTML

树形 DP

动态规划 · HTML

数学 / 逻辑形态

root 树后 postorder。dp[u][s] 表示 u 子树在 u 处于状态 s 时的答案;对每个 child v,将 dp[v][*] 按父子兼容规则 fold 进 u。

识别信号

容易误判的相似信号

SignalWhy it is different
一般图有环子问题不会因一条父边而独立;需图 DP、树分解或别的算法。
只求高度/总和简单递归聚合即可,不必引入多个 DP 状态。
路径可跨两个子树却只返回单一全局答案父节点通常需区分向上可延伸值与子树内部最优。

核心不变量

dfs(u,parent) 返回 u 子树在每个边界状态下的准确最优值;不同 child 子树仅通过 u 相互作用,因此可逐个合并。

状态、转移与处理顺序

ItemDefinition
State节点 u、父节点 parent 与 u 的有限边界模式;可有全局答案和向上返回摘要两类量。
Transitionpostorder 得到所有 child 状态后,按 u 的每种模式选择兼容 child 状态并求和/取极值。
Frontier / order以任意根展开的 DFS 后序;parent 参数阻止沿无向边返回。

Python 骨架

def max_non_adjacent(tree, values, root=0):
    if not tree:
        return 0
    def dfs(u, parent):
        skip, take = 0, values[u]
        for v in tree[u]:
            if v == parent: continue
            child_skip, child_take = dfs(v, u)
            take += child_skip
            skip += max(child_skip, child_take)
        return skip, take
    return max(dfs(root, -1))

正确性思路

  1. 叶节点的 skip=0、take=value 正确。
  2. 固定 u 是否选择后,不同子树独立;take 强制 child skip,skip 允许 child 最优二选一。
  3. 归纳得每个返回状态最优,根无父约束故取两态最大。

复杂度

TimeSpaceParameters
O(n·q²) 一般状态兼容;固定少量状态常为 O(n)O(n) 递归栈/状态n 为节点数,q 为每节点状态数。

边界条件

错误模式

PatternWhy it fails / fix
只返回一个值父节点对 child 的需求取决于自身模式;必须返回边界条件下的多个值。
无向树不跳过 parent递归会来回循环。
把全局路径与向上路径混为一谈跨两个 child 的最优路径不能整体继续向父延伸。
默认根具有特殊语义无根树算法应说明结果是否与任选根无关。

选择与排除规则

相关模板

RelationTemplateBoundary

原创微型例子

环节内容
Result选择两个叶子得 7。
Setup根权 5,两个叶子权 4 与 3,相邻节点不能同时选。
Trace根 take=5;根 skip=max(0,4)+max(0,3)=7。

Recall prompts

我的补充