Given a tree of N nodes and N-1 edges rooted at Node 1, an array points[] of size N, where points[i] denote the number of points at the vertex i and an integer k. A Node can be visited only if its ancestors have already been visited. When any Node i is visited 2 types of operations can be applied:
Type 1: Add (points[i] - k) points to total points.
Type 2: Add floor(points[i] / 2) points to total points and all the nodes j in the subtree of node i becomes floor(coins[j] / 2).
The task is to determine the maximum points that can be collected from all nodes.
Constraints:
2 <= N <= 10^5
0 <= points [i] <= 10^9
0 <= x <= 10^9
Examples:
Input: N=5, K=4
Collect Maximum Points from all Nodes
Output: 10 Explanation:
Type 1 operation is performed on Node 1, so points obtained = (7 - 4) = 3
Type 1 operation is performed on Node 3, so points obtained = (9 - 4) = 5
Type 2 operation is performed on Node 4, so points obtained = floor(5/2) = 2 and since Node 4 has no nodes in the subtree, therefore no other node's value gets reduced.
Type 2 operation is performed on Node 2, so points obtained = floor(0/2) = 0 and since Node 5 lies in the subtree of node 2, value of node 5 gets reduced to floor(3/2) = 1.
Type 2 operation is performed on Node 5, so points obtained = floor(1/2) = 0 and since Node 5 has no nodes in the subtree, therefore no other node's value gets reduced.
Total points obtained = 3 + 5 + 2 + 0 + 0 = 10
Input: N=3, K=0
Collect Maximum Points from all Nodes
Output: 7 Explanation:
Type 1 operation is performed in Node 1, so points obtained = (2 - 0) = 2
Type 1 operation is performed in Node 2, so points obtained = (2 - 0) = 2
Type 1 operation is performed in Node 3, so points obtained = (3 - 0) = 3
Approach: The problem can be solved using the following approach:
It can be observed that operation of type 2 can be applied at most 30 times because each type 2 operation reduces the value points at a node i to points[i]/2 and if 30 operations of type 2 are applied then node with any value up to 10^9 will get reduced to 0 as 230>109 so type 2 operation will be applied at most 30 times. Now we can apply Dynamic Programming to solve this problem. The state will be: dp[curr][i] = maximum points that can be collected at the subtree rooted at node curr such that type 2 operation are already applied i times on the ancestors till now. The answer will be max(dp[1][0], dp[1][1], dp[1][2], ...... , dp[1][30]).
Follow the steps to solve the problem:
Create a 2D dp[][] array of size N X 30 , where dp[curr][i] represents maximum points that can be collected at the subtree rooted at node curr with type 2 operation already applied i times on the ancestors till now.
Iterate through the nodes using DFS. At any node curr, dp[curr][i] will be calculated by:
Applying Type 1 Operation: Let sum1 denote the maximum points that can be collected from the subtree rooted at node curr if type 1 operation is performed on node curr. So sum1 will be: sum1=(pt-k) + \Sigma dp[x][i]
, where x is child of node curr and pt is the points at node curr when operation 2 have applied i times before visiting node curr.
Applying Type 2 Operation: Let sum2 denote the maximum points that can be collected from the subtree rooted at node curr if type 2 operation is performed on node curr. So sum2 will be: sum2=(pt/2) + \Sigma dp[x][i+1]
, where x is child of node curr and pt is the points at node curr when operation 2 have applied i times before visiting node curr.
dp[curr][i] will be max(sum1, sum2).
The final answer will be max(dp[1][0], dp[1][1], ......, dp[1][29], dp[1][30]).
Below is the implementation of above approach:
C++
#include<bits/stdc++.h>usingnamespacestd;// Depth-First Search (DFS) function to process the treevoiddfs(vector<vector<int>>&adj,vector<int>&points,vector<vector<int>>&dp,intk,intcurr,intpar){// Traverse the children nodes of the current nodefor(autox:adj[curr]){if(par!=x){dfs(adj,points,dp,k,x,curr);}}intpt=points[curr-1];// Loop for 30 iterations, corresponding to applying// type 2 operation at most 30 timesfor(inti=0;i<30;i++){intsum2=pt/2,sum1=pt-k;// Iterate through the child nodesfor(autox:adj[curr]){if(x!=par){sum2=sum2+dp[x][i+1];sum1=sum1+dp[x][i];}}pt=pt/2;// Update the DP values for the current node and// iterationdp[curr][i]=max(sum1,sum2);}}// Function to calculate the maximum pointsintmaximumPoints(vector<vector<int>>&edges,vector<int>&points,intk){intn=points.size();vector<vector<int>>adj(n+1);// Create an adjacency list based on the input edgesfor(inti=0;i<edges.size();i++){adj[edges[i][0]].push_back(edges[i][1]);adj[edges[i][1]].push_back(edges[i][0]);}// Initialize a 2D DP array with zerosvector<vector<int>>dp(n+1,vector<int>(31,0));// Perform DFS to calculate DP valuesdfs(adj,points,dp,k,1,-1);intans=0;// Find the maximum points for all iterationsfor(inti=0;i<31;i++){ans=max(ans,dp[1][i]);}returnans;}// Driver Codeintmain(){intN=5;intk=4;vector<vector<int>>edges={{1,2},{1,3},{1,4},{2,5}};vector<int>points={7,0,9,5,3};cout<<maximumPoints(edges,points,k);}
Java
importjava.util.*;// Nikunj SonigaraclassMain{// Depth-First Search (DFS) function to process the treestaticvoiddfs(List<List<Integer>>adj,List<Integer>points,List<List<Integer>>dp,intk,intcurr,intpar){// Traverse the children nodes of the current nodefor(intx:adj.get(curr)){if(par!=x){dfs(adj,points,dp,k,x,curr);}}intpt=points.get(curr-1);// Loop for 30 iterations, corresponding to applying// type 2 operation at most 30 timesfor(inti=0;i<30;i++){intsum2=pt/2,sum1=pt-k;// Iterate through the child nodesfor(intx:adj.get(curr)){if(x!=par){sum2=sum2+dp.get(x).get(i+1);sum1=sum1+dp.get(x).get(i);}}pt=pt/2;// Update the DP values for the current node and// iterationdp.get(curr).set(i,Math.max(sum1,sum2));}}// Function to calculate the maximum pointsstaticintmaximumPoints(List<List<Integer>>edges,List<Integer>points,intk){intn=points.size();List<List<Integer>>adj=newArrayList<>(n+1);// Initialize adjacency listfor(inti=0;i<=n;i++){adj.add(newArrayList<>());}// Create an adjacency list based on the input edgesfor(List<Integer>edge:edges){adj.get(edge.get(0)).add(edge.get(1));adj.get(edge.get(1)).add(edge.get(0));}// Initialize a 2D DP array with zerosList<List<Integer>>dp=newArrayList<>(n+1);for(inti=0;i<=n;i++){dp.add(newArrayList<>(31));for(intj=0;j<31;j++){dp.get(i).add(0);}}// Perform DFS to calculate DP valuesdfs(adj,points,dp,k,1,-1);intans=0;// Find the maximum points for all iterationsfor(inti=0;i<31;i++){ans=Math.max(ans,dp.get(1).get(i));}returnans;}// Driver Codepublicstaticvoidmain(String[]args){intN=5;intk=4;List<List<Integer>>edges=List.of(List.of(1,2),List.of(1,3),List.of(1,4),List.of(2,5));List<Integer>points=List.of(7,0,9,5,3);System.out.println(maximumPoints(edges,points,k));}}
Python3
# Depth-First Search (DFS) function to process the treedefdfs(adj,points,dp,k,curr,par):# Traverse the children nodes of the current nodeforxinadj[curr]:ifpar!=x:dfs(adj,points,dp,k,x,curr)pt=points[curr-1]# Loop for 30 iterations, corresponding to applying# type 2 operation at most 30 timesforiinrange(30):sum2,sum1=pt//2,pt-k# Iterate through the child nodesforxinadj[curr]:ifx!=par:sum2+=dp[x][i+1]sum1+=dp[x][i]pt//=2# Update the DP values for the current node and iterationdp[curr][i]=max(sum1,sum2)# Function to calculate the maximum pointsdefmaximumPoints(edges,points,k):n=len(points)adj=[[]for_inrange(n+1)]# Create an adjacency list based on the input edgesforedgeinedges:adj[edge[0]].append(edge[1])adj[edge[1]].append(edge[0])# Initialize a 2D DP array with zerosdp=[[0]*31for_inrange(n+1)]# Perform DFS to calculate DP valuesdfs(adj,points,dp,k,1,-1)ans=0# Find the maximum points for all iterationsforiinrange(31):ans=max(ans,dp[1][i])returnans# Driver Codedefmain():N=5k=4edges=[[1,2],[1,3],[1,4],[2,5]]points=[7,0,9,5,3]print(maximumPoints(edges,points,k))if__name__=="__main__":main()
C#
usingSystem;usingSystem.Collections.Generic;classMaximumPointsCalculator{// Depth-First Search (DFS) function to process the treestaticvoidDfs(List<List<int>>adj,List<int>points,List<List<int>>dp,intk,intcurr,intpar){// Traverse the children nodes of the current nodeforeach(intxinadj[curr]){if(par!=x){Dfs(adj,points,dp,k,x,curr);}}intpt=points[curr-1];// Loop for 30 iterations, corresponding to applying// type 2 operation at most 30 timesfor(inti=0;i<30;i++){intsum2=pt/2,sum1=pt-k;// Iterate through the child nodesforeach(intxinadj[curr]){if(x!=par){sum2=sum2+dp[x][i+1];sum1=sum1+dp[x][i];}}pt=pt/2;// Update the DP values for the current node and// iterationdp[curr][i]=Math.Max(sum1,sum2);}}// Function to calculate the maximum pointsstaticintMaximumPoints(List<List<int>>edges,List<int>points,intk){intn=points.Count;List<List<int>>adj=newList<List<int>>();// Initialize adjacency listfor(inti=0;i<=n;i++){adj.Add(newList<int>());}// Create an adjacency list based on the input edgesforeach(List<int>edgeinedges){adj[edge[0]].Add(edge[1]);adj[edge[1]].Add(edge[0]);}// Initialize a 2D DP array with zerosList<List<int>>dp=newList<List<int>>();for(inti=0;i<=n;i++){dp.Add(newList<int>(newint[31]));}// Perform DFS to calculate DP valuesDfs(adj,points,dp,k,1,-1);intans=0;// Find the maximum points for all iterationsfor(inti=0;i<31;i++){ans=Math.Max(ans,dp[1][i]);}returnans;}// Driver CodestaticvoidMain(string[]args){intk=4;List<List<int>>edges=newList<List<int>>{newList<int>{1,2},newList<int>{1,3},newList<int>{1,4},newList<int>{2,5}};List<int>points=newList<int>{7,0,9,5,3};Console.WriteLine(MaximumPoints(edges,points,k));}}
JavaScript
functiondfs(adj,points,dp,k,curr,par){// Traverse the children nodes of current nodefor(letxofadj[curr]){if(par!==x){dfs(adj,points,dp,k,x,curr);}}letpt=points[curr-1];// Loop for 30 iterations, corresponding to applyingfor(leti=0;i<30;i++){letsum2=Math.floor(pt/2);letsum1=pt-k;// Iterate through the child nodesfor(letxofadj[curr]){if(x!==par){sum2+=dp[x][i+1];sum1+=dp[x][i];}}pt=Math.floor(pt/2);// Update the DP values for the current node and iterationdp[curr][i]=Math.max(sum1,sum2);}}// Function to calculate the maximum pointsfunctionGFG(edges,points,k){constn=points.length;constadj=Array.from({length:n+1},()=>[]);// Create an adjacency list based on input edgesfor(leti=0;i<edges.length;i++){adj[edges[i][0]].push(edges[i][1]);adj[edges[i][1]].push(edges[i][0]);}// Initialize a 2D DP array with the zerosconstdp=Array.from({length:n+1},()=>Array(31).fill(0));dfs(adj,points,dp,k,1,-1);letans=0;// Find the maximum points for the all iterationsfor(leti=0;i<31;i++){ans=Math.max(ans,dp[1][i]);}returnans;}// Driver CodeconstN=5;constk=4;constedges=[[1,2],[1,3],[1,4],[2,5]];constpoints=[7,0,9,5,3];console.log(GFG(edges,points,k));
Output
10
Time Complexity: O(N), where N is number of nodes in the tree Auxiliary Space: O(N)