Problem
There exists an undirected tree rooted at node 0
with n
nodes labeled from
0
to n - 1
. You are given a 2D integer array edges
of length n -1
, where edges[i] = [ai, bi]
indicates that there is an edge between nodes
ai
and bi
in the tree. You are also given a 0-indexed array coins
of size n
where coins[i]
indicates the number of coins in the vertex i
, and an integer k
.
Starting from the root, you have to collect all the coins such that the coins at a node can only be collected if the coins of its ancestors have been already collected.
Coins at nodei
can be collected in one of the following ways:
- Collect all the coins, but you will get
coins[i] - k
points. Ifcoins[i] - k
is negative then you will loseabs(coins[i] - k)
points. - Collect all the coins, but you will get
floor(coins[i] / 2)
points. If this way is used, then for all thenodej
present in the subtree ofnodei
,coins[j]
will get reduced tofloor(coins[j] / 2)
.
Return themaximum points you can get after collecting the coins from all the tree nodes.
Examples
Example 1
|
|
Example 2
|
|
Constraints
n == coins.length
2 <= n <= 10^5
0 <= coins[i] <= 10^4
edges.length == n - 1
0 <= edges[i][0], edges[i][1] < n
0 <= k <= 10^4
Solution
Method 1 – Dynamic Programming on Trees (DFS with State)
Intuition
At each node, we have two choices: collect coins with penalty (coins[i] - k
) or collect coins with halving (and halve all coins in the subtree). We use DFS to compute, for each node, the maximum points for both choices, propagating the effect of halving down the tree. We use memoization to avoid recomputation.
Approach
- Build the tree as an adjacency list.
- Define a DFS function that returns the maximum points for a subtree rooted at
u
, with a flag indicating if the coins are halved. - For each node, try both options:
- Option 1: Collect with penalty, sum the best results from children (not halved).
- Option 2: Collect with halving, sum the best results from children (halved), and halve the coins for this node and all descendants.
- Use memoization to cache results for each node and halved state.
- Return the maximum of both options at the root.
Code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n * 2)
— Each node and state is visited at most twice (halved or not). - 🧺 Space complexity:
O(n)
— For the recursion stack and memoization.