cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 112 of 218
Ideas this builds on
1D dynamic programming112 / 218

Pick-or-skip DP grows branches

Picture

You learned to pick values from a row without choosing neighbors. Now values live on a tree, and you cannot pick both ends of any parent-child edge. A single unconditional child score is insufficient: the parent’s choice changes whether the child may be picked.

Predict

A child subtree’s best value is 10, achieved by taking its root. Can a parent that is also taken always add that 10?

Reveal the reasoning

No. That combination violates the adjacency rule. Return two answers from each child: its best value when its root is taken, and when its root is skipped.

Go deeper: condition the summary on the boundary

Represent nodes as (value,left,right). Let solve(node) return (take,skip). Taking forces both children to be skipped; skipping lets each child choose its better case. Picking nothing is allowed.

def tree_pick(root):
    def solve(node):
        if node is None:
            return 0, 0
        value, left, right = node
        lt, ls = solve(left)
        rt, rs = solve(right)
        take = value + ls + rs
        skip = max(lt, ls) + max(rt, rs)
        return take, skip
    return max(solve(root))

assert tree_pick((5, (4, None, None), (4, None, None))) == 8
assert tree_pick((-5, None, None)) == 0
assert tree_pick(None) == 0

After conditioning on whether a node is selected, its child subtrees are independent under these rules. That explains why their contributions can be added. Each node computes two values once: O(n) time and O(h) recursion space, without needing a separate memoization dictionary on a proper tree.

This is a useful correction to “DP means adding a cache.” The important feature here is the conditional subproblem values and recurrence; the traversal already ensures each subproblem is evaluated once.

For a general graph with cross-edges between branches, those supposedly separate subtrees can constrain each other. Applying the same recurrence would ignore those edges. The tree structure makes the small boundary summary sufficient.

Analogy limit: two return values do not automatically mean “2D DP” in the usual table sense. One can describe the logical state as (node, selected_status), but implementation and naming conventions vary; explain its information rather than defending a label.

Change one rule

Selected nodes must be at graph distance at least 3, rather than merely non-adjacent. Are take/skip summaries still enough?

Check the variation

No. Selections in different child branches can now conflict through their parent. The boundary summary needs enough distance information to check those interactions before combining children.

Connect

Tree diameter separates the summary sent upward from a candidate answer through the node. Lowest common ancestor also combines child evidence. Recognition asks whether branches really are independent.