Maximum Score After Applying Operations on a Tree

medium tree dfs dp

Problem

You are given a tree rooted at node 0 where each node holds a value. In one operation you may pick any node, add its value to your score, and set that node's value to 0. The tree must stay healthy: the sum of values on every path from the root to a leaf must remain greater than 0 — so each root-to-leaf path must keep at least one non-zero node.

Return the maximum score you can collect. Equivalently, the score equals the total of all values minus the minimum amount you are forced to leave behind to keep every path healthy.

Inputvalues = [20,10,9,7,4,3,5] (as a rooted tree)
Output40
Total is 58. Each subtree keeps the cheaper of its own root value or its children's required keep, forcing 18 to stay → score 58 − 18 = 40.

def maximum_score_after_operations(root):
    total = [0]
    def collect(node):
        if node:
            total[0] += node.val
            collect(node.left)
            collect(node.right)
    collect(root)

    def min_keep(node):
        if not node:
            return 0
        if not node.left and not node.right:
            return node.val
        children = min_keep(node.left) + min_keep(node.right)
        return min(node.val, children)

    return total[0] - min_keep(root)
function maximumScoreAfterOperations(root) {
  let total = 0;
  (function collect(node) {
    if (!node) return;
    total += node.val;
    collect(node.left);
    collect(node.right);
  })(root);

  function minKeep(node) {
    if (!node) return 0;
    if (!node.left && !node.right) return node.val;
    const children = minKeep(node.left) + minKeep(node.right);
    return Math.min(node.val, children);
  }

  return total - minKeep(root);
}
class Solution {
    private long total = 0;
    public long maximumScoreAfterOperations(TreeNode root) {
        collect(root);
        return total - minKeep(root);
    }
    private void collect(TreeNode node) {
        if (node == null) return;
        total += node.val;
        collect(node.left);
        collect(node.right);
    }
    private long minKeep(TreeNode node) {
        if (node == null) return 0;
        if (node.left == null && node.right == null) return node.val;
        long children = minKeep(node.left) + minKeep(node.right);
        return Math.min(node.val, children);
    }
}
long long total = 0;
void collect(TreeNode* node) {
    if (!node) return;
    total += node->val;
    collect(node->left);
    collect(node->right);
}
long long minKeep(TreeNode* node) {
    if (!node) return 0;
    if (!node->left && !node->right) return node->val;
    long long children = minKeep(node->left) + minKeep(node->right);
    return min((long long)node->val, children);
}
long long maximumScoreAfterOperations(TreeNode* root) {
    collect(root);
    return total - minKeep(root);
}
Time: O(n) Space: O(h)