Maximum coins such that root to leaf path sum is positive
Last Updated :
24 Feb, 2024
Given tree with N vertices rooted at node 0, edges given by array edges[][] and array arr[] of size N representing coins[] on each node. In one operation pick any node and collect all its coins. Task for this problem is to find maximum number of coins collected such that path sum from root node to any leaf node remains positive (path sum from root node to leaf node is total coins present on nodes of simple path between root to leaf).
Examples:
Input: N = 6, A[] = {5, 2, 5, 2, 1, 1 }, edges[][2] = {{0, 1}, {0, 2}, {0, 3}, {2, 4}, {4, 5}}
Output: 11
Explanation: We can collect coins from node 1, 2, 3, 4 and 5. Total coins = 2 + 5 + 2 + 1 + 1 = 11.
Since root node 0 is non zero any path starting from root node to any leaf will be non zero.
Input: N = 7, A[] = { 20, 10, 9, 7, 4, 3, 5 }, edges[][2] = { {0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6} }
Output: 40
Explanation: We can collect coins from nodes 0, 2, 3 and 4. Total coins = 20 + 9 + 7 + 4 = 40
- path sum from 0 to 4 is equal to 10.
- path sum from 0 to 3 is equal to 10.
- path sum from 0 to 5 is equal to 3.
- path sum from 0 to 6 is equal to 5.
So, path sum from root node 0 to any leaf is non-zero.
Approach: To solve the problem, follow the below idea:
Observation: We have two choices to make for every subtree root. Either we pick the coins present on root of subtree or all coins on present on its descendants. Problem is turned into other way around lets find minimum coins required to keep path sum from root node to any leaf node non-zero.
Tree Dynamic Programming can be used to solve this problem. The main concept of DP in the problem will be:
DP[v] will store minimum coins required so path sum from node v to any leaf node is non-zero.
Transition: dp[v] = min(A[v], ∑dp[ui])
Step-by-step algorithm:
- Declaring Adjacency list adj[N] and fill the adjacency list by iterating on N – 1 edges.
- Declaring DP[] array of length N.
- Declare dfs function which takes two parameters as input v node and p its parent.
- Iterate over all child’s u and find out dp[v] = ∑dp[ui]
- base case if v is not zero and there is only one element present in adjacent of v then update dp[v] as A[v]
- otherwise update dp[v] = min(dp[v], A[v])
- Call dfs(0, -1) function which is called for node 0 and its parent being -1
- Declare variable totalCoins which has sum of all coins present on every node of v
- Return totalCoins – dp[0]
Below is the implementation of the approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxCoinsCollect( int N, int edges[][2], int A[])
{
vector<vector< int > > adj(N);
for ( int i = 0; i < N - 1; i++) {
adj[edges[i][0]].push_back(edges[i][1]);
adj[edges[i][1]].push_back(edges[i][0]);
}
vector< int > dp(N, 0);
auto dfs = [&]( int v, int p, auto && dfs) -> void {
for ( auto & u : adj[v]) {
if (u != p) {
dfs(u, v, dfs);
dp[v] += dp[u];
}
}
if (v != 0 and adj[v].size() == 1)
dp[v] = A[v];
else
dp[v] = min(dp[v], A[v]);
};
dfs(0, N, dfs);
int totalCoins = accumulate(A, A + N, 0);
return totalCoins - dp[0];
}
int main()
{
int N = 6;
int A[] = { 5, 2, 5, 2, 1, 1 };
int edges[][2] = {
{ 0, 1 }, { 0, 2 }, { 0, 3 }, { 2, 4 }, { 4, 5 }
};
cout << maxCoinsCollect(N, edges, A) << endl;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class MaxCoinsCollect {
static int maxCoinsCollect( int N, List< int []> edges, int [] A) {
List<List<Integer>> adj = new ArrayList<>();
for ( int i = 0 ; i < N; i++) {
adj.add( new ArrayList<>());
}
for ( int [] edge : edges) {
adj.get(edge[ 0 ]).add(edge[ 1 ]);
adj.get(edge[ 1 ]).add(edge[ 0 ]);
}
int [] dp = new int [N];
dfs( 0 , - 1 , adj, dp, A);
int totalCoins = 0 ;
for ( int coin : A) {
totalCoins += coin;
}
return totalCoins - dp[ 0 ];
}
static void dfs( int v, int p, List<List<Integer>> adj, int [] dp, int [] A) {
for ( int u : adj.get(v)) {
if (u != p) {
dfs(u, v, adj, dp, A);
dp[v] += dp[u];
}
}
if (v != 0 && adj.get(v).size() == 1 ) {
dp[v] = A[v];
} else {
dp[v] = Math.min(dp[v], A[v]);
}
}
public static void main(String[] args) {
int N = 6 ;
int [] A = { 5 , 2 , 5 , 2 , 1 , 1 };
List< int []> edges = List.of(
new int []{ 0 , 1 }, new int []{ 0 , 2 },
new int []{ 0 , 3 }, new int []{ 2 , 4 }, new int []{ 4 , 5 }
);
System.out.println(maxCoinsCollect(N, edges, A));
}
}
|
Python3
def max_coins_collect(N, edges, A):
adj = [[] for _ in range (N)]
for edge in edges:
adj[edge[ 0 ]].append(edge[ 1 ])
adj[edge[ 1 ]].append(edge[ 0 ])
dp = [ 0 ] * N
def dfs(v, p):
for u in adj[v]:
if u ! = p:
dfs(u, v)
dp[v] + = dp[u]
if v ! = 0 and len (adj[v]) = = 1 :
dp[v] = A[v]
else :
dp[v] = min (dp[v], A[v])
dfs( 0 , - 1 )
total_coins = sum (A)
return total_coins - dp[ 0 ]
if __name__ = = "__main__" :
N = 6
A = [ 5 , 2 , 5 , 2 , 1 , 1 ]
edges = [
[ 0 , 1 ], [ 0 , 2 ], [ 0 , 3 ], [ 2 , 4 ], [ 4 , 5 ]
]
print (max_coins_collect(N, edges, A))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static int MaxCoinsCollect( int N, int [,] edges, int [] A)
{
var adj = new List<List< int >>(N);
for ( int i = 0; i < N; i++)
{
adj.Add( new List< int >());
}
for ( int i = 0; i < N - 1; i++)
{
adj[edges[i, 0]].Add(edges[i, 1]);
adj[edges[i, 1]].Add(edges[i, 0]);
}
var dp = new int [N];
Action< int , int > dfs = null ;
dfs = (v, p) =>
{
foreach ( var u in adj[v])
{
if (u != p)
{
dfs(u, v);
dp[v] += dp[u];
}
}
if (v != 0 && adj[v].Count == 1)
dp[v] = A[v];
else
dp[v] = Math.Min(dp[v], A[v]);
};
dfs(0, N);
int totalCoins = A.Sum();
return totalCoins - dp[0];
}
static void Main( string [] args)
{
int N = 6;
int [] A = { 5, 2, 5, 2, 1, 1 };
int [,] edges = {
{ 0, 1 }, { 0, 2 }, { 0, 3 }, { 2, 4 }, { 4, 5 }
};
Console.WriteLine(MaxCoinsCollect(N, edges, A));
}
}
|
Javascript
function maxCoinsCollect(N, edges, A) {
let adj = new Array(N).fill().map(() => []);
for (let edge of edges) {
let [u, v] = edge;
adj[u].push(v);
adj[v].push(u);
}
let dp = new Array(N).fill(0);
dfs(0, -1, adj, dp, A);
let totalCoins = A.reduce((acc, coin) => acc + coin, 0);
return totalCoins - dp[0];
}
function dfs(v, p, adj, dp, A) {
for (let u of adj[v]) {
if (u !== p) {
dfs(u, v, adj, dp, A);
dp[v] += dp[u];
}
}
if (v !== 0 && adj[v].length === 1) {
dp[v] = A[v];
} else {
dp[v] = Math.min(dp[v], A[v]);
}
}
( function () {
let N = 6;
let A = [5, 2, 5, 2, 1, 1];
let edges = [
[0, 1], [0, 2],
[0, 3], [2, 4], [4, 5]
];
console.log(maxCoinsCollect(N, edges, A));
})();
|
Time Complexity: O(N), where N is the number of nodes in the tree.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...