Given an N-array tree of N nodes, rooted at 1, with edges in the form {u, v}, and an array values[] consisting of N integers. Each vertex i has an integer value denoted by values[i]. The task is to find the largest Subtree Sum possible for each vertex i by adding its value to a non-empty subset of its child vertices.
Examples:
Input: Edges[][] = {{1, 2}, {1, 3}, {3, 4}}, values[] = {1, -1, 0, 1}
Output: 2 -1 1 1
Explanation:
Below is the given Tree:1
/ \
2 3
\
4
Following subsets can be chosen for each vertex:
Vertex 1: Subset of vertices {1, 3, 4} can be chosen with values {1, 0, 1}. Therefore, sum = 1 + 0 + 1 = 2.
Vertex 2: Subset of vertices {2} can be chosen with values {-1}. Therefore, sum = -1.
Vertex 3: Subset of vertices {3, 4} can be chosen with values {0, 1}. Therefore, sum = 0 + 1 = 1.
Vertex 4: Subset of vertices {4} can be chosen with values {1}. Therefore, sum = 1.Input: Edges[][] = {{1, 2}, {1, 3}, {2, 4}, {2, 5}}, values[] = {1, -1, -2, 1, 3}
Output: 5 4 -2 1 3
Explanation:
Below is the given Tree:1
/ \
2 3
/ \
4 5
Following subsets can be chosen for each vertex:
Vertex 1: Subset of vertices {1, 4, 5} can be chosen with values {1, 1, 3}. Therefore, sum = 1 + 1 + 3 = 5.
Vertex 2: Subset of vertices {4, 5} can be chosen with values {1, 3}. Therefore, sum = 1 + 3 = 4.
Vertex 3: Subset of vertices {3} can be chosen with values {-2}. Therefore, sum = -2.
Vertex 4: Subset of vertices {4} can be chosen with values {1}. Therefore, sum = 1.
Vertex 5: Subset of vertices {5} can be chosen with values {3}. Therefore, sum = 3.
Naive Approach: The simplest approach is to traverse the subtree of each vertex i from 1 to N and perform DFS Traversal on it. For each vertex i, choose the subset of its child vertices having non-negative values. If the subset of chosen vertices is empty, then search and print the node having the minimum value such that it is the child node of vertex i. Otherwise, print the sum of node values of nodes present in the subset.
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: The idea is to use DFS Traversal and Dynamic programming approach. Follow the below steps to solve the problem:
- Initialize an array ans[] of size N to store the maximum subtree sum for each vertex.
- Perform DFS Traversal for each vertex and for each vertex initialize v, ans[v] with some large negative value.
- If vertex v is a leaf vertex, then the answer for that vertex would be values[v]. Therefore, assign ans[v] = values[v].
- Otherwise, traverse the vertices adjacent to vertex v and for each adjacent vertex u, update ans[v] as ans[v] = max(ans[u] + values[v], values[v], ans[u]).
- After the above steps, print the values stored in ans[] array as the answer for each vertex.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; #define V 3 #define M 2 // Function to perform the DFS // Traversal on the given Tree void dfs( int v, int p, vector< int > adj[], int ans[], int vals[]) { // To check if v is leaf vertex bool isLeaf = 1; // Initialize answer for vertex v ans[v] = INT_MIN; // Traverse adjacency list of v for ( int u : adj[v]) { if (u == p) continue ; isLeaf = 0; dfs(u, v, adj, ans, vals); // Update maximum subtree sum ans[v] = max(ans[u] + vals[v], max(ans[u], vals[u])); } // If v is leaf if (isLeaf) { ans[v] = vals[v]; } } // Function to calculate maximum // subtree sum for each vertex void printAnswer( int n, int edges[V][M], int values[]) { // Stores the adjacency list vector< int > adj[n]; // Add Edges to the list for ( int i = 0; i < n - 1; i++) { int u = edges[i][0] - 1; int v = edges[i][1] - 1; adj[u].push_back(v); adj[v].push_back(u); } // Stores largest subtree // sum for each vertex int ans[n] ; // Calculate answer dfs(0, -1, adj, ans, values); // Print the result for ( auto x : ans) { cout << x << " " ; } } // Driver Code int main() { // Given nodes int N = 4; // Give N edges int edges[V][M] = { { 1, 2 }, { 1, 3 }, { 3, 4 } }; // Given values int values[] = { 1, -1, 0, 1 }; // Function Call printAnswer(N, edges, values); } // This code is contributed by Princi Singh |
Java
// Java program for the above approach import java.io.*; import java.util.ArrayList; @SuppressWarnings ( "unchecked" ) class GFG { // Function to perform the DFS // Traversal on the given Tree static void dfs( int v, int p, ArrayList<Integer> adj[], int ans[], int vals[]) { // To check if v is leaf vertex boolean isLeaf = true ; // Initialize answer for vertex v ans[v] = Integer.MIN_VALUE; // Traverse adjacency list of v for ( int u : adj[v]) { if (u == p) continue ; isLeaf = false ; dfs(u, v, adj, ans, vals); // Update maximum subtree sum ans[v] = Math.max( ans[u] + vals[v], Math.max(ans[u], vals[u])); } // If v is leaf if (isLeaf) { ans[v] = vals[v]; } } // Function to calculate maximum // subtree sum for each vertex static void printAnswer( int n, int edges[][], int values[]) { // Stores the adjacency list ArrayList<Integer> adj[] = new ArrayList[n]; for ( int i = 0 ; i < n; i++) adj[i] = new ArrayList<>(); // Add Edges to the list for ( int i = 0 ; i < n - 1 ; i++) { int u = edges[i][ 0 ] - 1 ; int v = edges[i][ 1 ] - 1 ; adj[u].add(v); adj[v].add(u); } // Stores largest subtree // sum for each vertex int ans[] = new int [n]; // Calculate answer dfs( 0 , - 1 , adj, ans, values); // Print the result for ( int x : ans) { System.out.print(x + " " ); } } // Driver Code public static void main(String[] args) { // Given nodes int N = 4 ; // Give N edges int edges[][] = new int [][] { { 1 , 2 }, { 1 , 3 }, { 3 , 4 } }; // Given values int values[] = { 1 , - 1 , 0 , 1 }; // Function Call printAnswer(N, edges, values); } } |
Python3
# Python3 program for the above approach V = 3 M = 2 # Function to perform the DFS # Traversal on the given Tree def dfs(v, p): # To check if v is leaf vertex isLeaf = 1 # Initialize answer for vertex v ans[v] = - 10 * * 9 # Traverse adjacency list of v for u in adj[v]: if (u = = p): continue isLeaf = 0 dfs(u, v) # Update maximum subtree sum ans[v] = max (ans[u] + vals[v], max (ans[u], vals[u])) # If v is leaf if (isLeaf): ans[v] = vals[v] # Function to calculate maximum # subtree sum for each vertex def printAnswer(n, edges, vals): # Stores the adjacency list # vector<int> adj[n]; # Add Edges to the list for i in range (n - 1 ): u = edges[i][ 0 ] - 1 v = edges[i][ 1 ] - 1 adj[u].append(v) adj[v].append(u) # Calculate answer dfs( 0 , - 1 ) # Print the result for x in ans: print (x, end = " " ) # Driver Code if __name__ = = '__main__' : # Given nodes N = 4 # Give N edges edges = [ [ 1 , 2 ], [ 1 , 3 ], [ 3 , 4 ] ] adj = [[] for i in range (N)] ans = [ 0 for i in range (N)] # Given values vals = [ 1 , - 1 , 0 , 1 ] # Function Call printAnswer(N, edges, vals) # This code is contributed by mohit kumar 29 |
C#
// C# program for the // above approach using System; using System.Collections.Generic; class GFG{ // Function to perform the DFS // Traversal on the given Tree static void dfs( int v, int p, List< int > []adj, int []ans, int []vals) { // To check if v is leaf // vertex bool isLeaf = true ; // Initialize answer for // vertex v ans[v] = int .MinValue; // Traverse adjacency list // of v foreach ( int u in adj[v]) { if (u == p) continue ; isLeaf = false ; dfs(u, v, adj, ans, vals); // Update maximum subtree // sum ans[v] = Math.Max(ans[u] + vals[v], Math.Max(ans[u], vals[u])); } // If v is leaf if (isLeaf) { ans[v] = vals[v]; } } // Function to calculate maximum // subtree sum for each vertex static void printAnswer( int n, int [,]edges, int []values) { // Stores the adjacency list List< int > []adj = new List< int >[n]; for ( int i = 0; i < n; i++) adj[i] = new List< int >(); // Add Edges to the list for ( int i = 0; i < n - 1; i++) { int u = edges[i, 0] - 1; int v = edges[i, 1] - 1; adj[u].Add(v); adj[v].Add(u); } // Stores largest subtree // sum for each vertex int []ans = new int [n]; // Calculate answer dfs(0, -1, adj, ans, values); // Print the result foreach ( int x in ans) { Console.Write(x + " " ); } } // Driver Code public static void Main(String[] args) { // Given nodes int N = 4; // Give N edges int [,]edges = new int [,] {{1, 2}, {1, 3}, {3, 4}}; // Given values int []values = {1, -1, 0, 1}; // Function Call printAnswer(N, edges, values); } } // This code is contributed by gauravrajput1 |
Javascript
<script> // JavaScript program for the above approach // Function to perform the DFS // Traversal on the given Tree function dfs(v, p, adj, ans, vals) { // To check if v is leaf // vertex let isLeaf = true ; // Initialize answer for // vertex v ans[v] = Number.MIN_VALUE; // Traverse adjacency list // of v for (let u = 0; u < adj[v].length; u++) { if (adj[v][u] == p) continue ; isLeaf = false ; dfs(adj[v][u], v, adj, ans, vals); // Update maximum subtree // sum ans[v] = Math.max(ans[adj[v][u]] + vals[v], Math.max(ans[adj[v][u]], vals[adj[v][u]])); } // If v is leaf if (isLeaf) { ans[v] = vals[v]; } } // Function to calculate maximum // subtree sum for each vertex function printAnswer(n, edges, values) { // Stores the adjacency list let adj = new Array(n); for (let i = 0; i < n; i++) adj[i] = []; // Add Edges to the list for (let i = 0; i < n - 1; i++) { let u = edges[i][0] - 1; let v = edges[i][1] - 1; adj[u].push(v); adj[v].push(u); } // Stores largest subtree // sum for each vertex let ans = new Array(n); // Calculate answer dfs(0, -1, adj, ans, values); // Print the result for (let x = 0; x < ans.length; x++) { document.write(ans[x] + " " ); } } // Given nodes let N = 4; // Give N edges let edges = [[1, 2], [1, 3], [3, 4]]; // Given values let values = [1, -1, 0, 1]; // Function Call printAnswer(N, edges, values); </script> |
2 -1 1 1
Time Complexity: O(N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!