PrepStack · Markdown HTML

Tree dynamic programming

Dynamic programming · HTML

Formal shape

Root the tree and process postorder. dp[u][s] is the answer in u's subtree when u has boundary mode s; fold every child's states into u under parent-child compatibility rules.

Recognition signals

False friends

SignalWhy it is different
A cyclic general graphOne parent edge does not isolate subproblems; use graph DP, decomposition, or another method.
Only height or a simple sumA single recursive aggregate is enough; multiple DP modes add no value.
A path may cross two childrenA single undifferentiated answer cannot both represent the subtree optimum and a path extendable upward.

Core invariant

dfs(u,parent) returns the exact optimum for every boundary mode of u's subtree. Distinct child subtrees interact only through u and can therefore be folded independently.

State, transition, and processing order

ItemDefinition
StateNode u, its parent, and a finite boundary mode for u; distinguish globally complete values from summaries extendable to the parent.
TransitionAfter all children return postorder, choose compatible child modes for each mode of u and aggregate by sum or extreme.
Frontier / orderPostorder DFS from any root, with parent preventing traversal back over an undirected edge.

Python skeleton

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))

Correctness sketch

  1. For a leaf, skip=0 and take=value are exact.
  2. Once u's mode is fixed, child subtrees are independent: take forces each child to skip, while skip permits the child's better mode.
  3. Induction proves both returned modes; the root has no parent restriction, so choose its better mode.

Complexity

TimeSpaceParameters
O(n·q²) for general compatibility, often O(n) for constant small qO(n) stack/staten is node count and q states per node.

Edge cases

Error patterns

PatternWhy it fails / fix
Returning one value onlyA parent's legal choice depends on the child's boundary mode; return every required mode.
Not skipping parent in an undirected treeRecursion immediately cycles across the same edge.
Mixing global and upward path valuesA path joining two children is complete and cannot continue upward as a whole.
Giving the chosen root special meaningFor an unrooted problem, explain why an arbitrary root preserves the answer.

Selection and exclusion rules

RelationTemplateBoundary

Original micro-example

PartDetail
ResultThe optimal selection is the two leaves with total 7.
SetupA root has weight 5 and two leaves have weights 4 and 3; adjacent nodes cannot both be selected.
TraceTaking the root yields 5; skipping it permits both leaves for 4+3=7.

Recall prompts

My notes