Open In App

Maximum coins such that root to leaf path sum is positive

Last Updated : 24 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to Find maximum coins collected
// from tree such that path sum from root node
// to any leaf node is non zero
int maxCoinsCollect(int N, int edges[][2], int A[])
{
    // Declaring Adjacency List for tree
    vector<vector<int> > adj(N);
 
    // Filling Adjacency List
    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]);
    }
 
    // DP array initalized with zero
    vector<int> dp(N, 0);
 
    // dfs function
    auto dfs = [&](int v, int p, auto&& dfs) -> void {
        // iterating over child nodes
        for (auto& u : adj[v]) {
 
            // if child of v is not equal to its parent
            if (u != p) {
 
                // call dfs function for child u
                dfs(u, v, dfs);
 
                // adding maximum coins chosen for child
                // nodes
                dp[v] += dp[u];
            }
        }
 
        // base case
        if (v != 0 and adj[v].size() == 1)
            dp[v] = A[v];
        else
            // Either chose maximum coins by child nodes or
            // coins present on root of the tree
            dp[v] = min(dp[v], A[v]);
    };
 
    // calling dfs function
    dfs(0, N, dfs);
 
    // variable to store total coins
    int totalCoins = accumulate(A, A + N, 0);
 
    // returning final answer totalCoins - minimum
    // coins required so that path sum from root to
    // any leaf node is non zero
    return totalCoins - dp[0];
}
 
// Driver Code
int main()
{
 
    // Input
    int N = 6;
    int A[] = { 5, 2, 5, 2, 1, 1 };
    int edges[][2] = {
        { 0, 1 }, { 0, 2 }, { 0, 3 }, { 2, 4 }, { 4, 5 }
    };
 
    // Function Call
    cout << maxCoinsCollect(N, edges, A) << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
 
public class MaxCoinsCollect {
 
    // Function to find maximum coins collected
    // from the tree such that path sum from the
    // root node to any leaf node is non zero
    static int maxCoinsCollect(int N, List<int[]> edges, int[] A) {
        // Declaring Adjacency List for the tree
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            adj.add(new ArrayList<>());
        }
 
        // Filling Adjacency List
        for (int[] edge : edges) {
            adj.get(edge[0]).add(edge[1]);
            adj.get(edge[1]).add(edge[0]);
        }
 
        // DP array initialized with zero
        int[] dp = new int[N];
 
        // dfs function
        dfs(0, -1, adj, dp, A);
 
        // variable to store total coins
        int totalCoins = 0;
        for (int coin : A) {
            totalCoins += coin;
        }
 
        // returning final answer totalCoins - minimum
        // coins required so that the path sum from root to
        // any leaf node is non-zero
        return totalCoins - dp[0];
    }
 
    // DFS function
    static void dfs(int v, int p, List<List<Integer>> adj, int[] dp, int[] A) {
        // iterating over child nodes
        for (int u : adj.get(v)) {
            // if child of v is not equal to its parent
            if (u != p) {
                // call dfs function for child u
                dfs(u, v, adj, dp, A);
                // adding maximum coins chosen for child nodes
                dp[v] += dp[u];
            }
        }
 
        // base case
        if (v != 0 && adj.get(v).size() == 1) {
            dp[v] = A[v];
        } else {
            // Either choose maximum coins by child nodes or
            // coins present on the root of the tree
            dp[v] = Math.min(dp[v], A[v]);
        }
    }
 
    // Driver Code
    public static void main(String[] args) {
        // Input
        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}
        );
 
        // Function Call
        System.out.println(maxCoinsCollect(N, edges, A));
    }
}


Python3




# Python code to implement the approach
 
# Function to find maximum coins collected
# from the tree such that path sum from the
# root node to any leaf node is non zero
 
 
def max_coins_collect(N, edges, A):
    # Declaring Adjacency List for tree
    adj = [[] for _ in range(N)]
 
    # Filling Adjacency List
    for edge in edges:
        adj[edge[0]].append(edge[1])
        adj[edge[1]].append(edge[0])
 
    # DP array initialized with zero
    dp = [0] * N
 
    # dfs function
    def dfs(v, p):
        # iterating over child nodes
        for u in adj[v]:
            # if child of v is not equal to its parent
            if u != p:
                # call dfs function for child u
                dfs(u, v)
                # adding maximum coins chosen for child nodes
                dp[v] += dp[u]
 
        # base case
        if v != 0 and len(adj[v]) == 1:
            dp[v] = A[v]
        else:
            # Either choose maximum coins by child nodes or
            # coins present on the root of the tree
            dp[v] = min(dp[v], A[v])
 
    # calling dfs function
    dfs(0, -1)
 
    # variable to store total coins
    total_coins = sum(A)
 
    # returning final answer total_coins - minimum
    # coins required so that path sum from root to
    # any leaf node is non zero
    return total_coins - dp[0]
 
 
# Driver Code
if __name__ == "__main__":
    # Input
    N = 6
    A = [5, 2, 5, 2, 1, 1]
    edges = [
        [0, 1], [0, 2], [0, 3], [2, 4], [4, 5]
    ]
 
    # Function Call
    print(max_coins_collect(N, edges, A))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    // Function to Find maximum coins collected
    // from tree such that path sum from root node
    // to any leaf node is non zero
    static int MaxCoinsCollect(int N, int[,] edges, int[] A)
    {
        // Declaring Adjacency List for tree
        var adj = new List<List<int>>(N);
 
        for (int i = 0; i < N; i++)
        {
            adj.Add(new List<int>());
        }
 
        // Filling Adjacency List
        for (int i = 0; i < N - 1; i++)
        {
            adj[edges[i, 0]].Add(edges[i, 1]);
            adj[edges[i, 1]].Add(edges[i, 0]);
        }
 
        // DP array initialized with zero
        var dp = new int[N];
 
        // dfs function
        Action<int, int> dfs = null;
        dfs = (v, p) =>
        {
            // iterating over child nodes
            foreach (var u in adj[v])
            {
                // if child of v is not equal to its parent
                if (u != p)
                {
                    // call dfs function for child u
                    dfs(u, v);
 
                    // adding maximum coins chosen for child nodes
                    dp[v] += dp[u];
                }
            }
 
            // base case
            if (v != 0 && adj[v].Count == 1)
                dp[v] = A[v];
            else
                // Either chose maximum coins by child nodes or
                // coins present on root of the tree
                dp[v] = Math.Min(dp[v], A[v]);
        };
 
        // calling dfs function
        dfs(0, N);
 
        // variable to store total coins
        int totalCoins = A.Sum();
 
        // returning final answer totalCoins - minimum
        // coins required so that path sum from root to
        // any leaf node is non zero
        return totalCoins - dp[0];
    }
 
    // Driver Code
    static void Main(string[] args)
    {
        // Input
        int N = 6;
        int[] A = { 5, 2, 5, 2, 1, 1 };
        int[,] edges = {
            { 0, 1 }, { 0, 2 }, { 0, 3 }, { 2, 4 }, { 4, 5 }
        };
 
        // Function Call
        Console.WriteLine(MaxCoinsCollect(N, edges, A));
    }
}


Javascript




// Function to find maximum coins collected
// from the tree such that path sum from the
// root node to any leaf node is non zero
function maxCoinsCollect(N, edges, A) {
    // Declaring Adjacency List for the tree
    let adj = new Array(N).fill().map(() => []);
 
    // Filling Adjacency List
    for (let edge of edges) {
        let [u, v] = edge;
        adj[u].push(v);
        adj[v].push(u);
    }
 
    // DP array initialized with zero
    let dp = new Array(N).fill(0);
 
    // dfs function
    dfs(0, -1, adj, dp, A);
 
    // variable to store total coins
    let totalCoins = A.reduce((acc, coin) => acc + coin, 0);
 
    // returning final answer totalCoins - minimum
    // coins required so that the path sum from root to
    // any leaf node is non-zero
    return totalCoins - dp[0];
}
 
// DFS function
function dfs(v, p, adj, dp, A) {
    // iterating over child nodes
    for (let u of adj[v]) {
        // if child of v is not equal to its parent
        if (u !== p) {
            // call dfs function for child u
            dfs(u, v, adj, dp, A);
            // adding maximum coins chosen for child nodes
            dp[v] += dp[u];
        }
    }
 
    // base case
    if (v !== 0 && adj[v].length === 1) {
        dp[v] = A[v];
    } else {
        // Either choose maximum coins by child nodes or
        // coins present on the root of the tree
        dp[v] = Math.min(dp[v], A[v]);
    }
}
 
// Driver Code
(function() {
    // Input
    let N = 6;
    let A = [5, 2, 5, 2, 1, 1];
    let edges = [
        [0, 1], [0, 2],
        [0, 3], [2, 4], [4, 5]
    ];
 
    // Function Call
    console.log(maxCoinsCollect(N, edges, A));
})();


Output

11


Time Complexity: O(N), where N is the number of nodes in the tree.
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads