Open In App

Largest subtree sum for each vertex of given N-ary Tree

Improve
Improve
Like Article
Like
Save
Share
Report

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>


Output: 

2 -1 1 1

 

Time Complexity: O(N)
Auxiliary Space: O(N)



Last Updated : 28 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads