Use DFS with post-order processing. Visit children before processing the current node. This ensures you have all child results before computing the parent's result.
function dfs(u, parent)
for each child v of u
if v != parent then
dfs(v, u)
// Now process u using results from children
compute dp[u] from dp[children]
The recursion naturally handles the tree structure. Post-order means you work from leaves up to the root. This bottom-up flow is the essence of subtree DP.