Open In App

Maximum possible score that can be obtained by constructing a Binary Tree based on given conditions

Given an array arr[] of (N – 1) integers and each value arr[i](1-based indexing) is the score of the nodes having degree i. The task is to determine the maximum score of any tree of N nodes that can be constructed.

Examples:



Input: arr[] = {1, 3, 0}
Output: 8
Explanation:
One possible way to construct tree is:
                         1
                       /   \
                     2     3
                              \
                              4
Node 1 have degree 2. Therefore, its score is 3.
Node 2 have degree 1. Therefore, its score is 1.
Node 3 have degree 2. Therefore, its score is 3.
Node 4 have degree 1. Therefore, its score is 1.
Therefore, the total score = 3 + 1 + 3 + 1 = 8.

Input: arr[] = {0, 1}
Output: 1
Explanation:
One possible way to construct tree is:
                         1
                       /   \
                     2     3
Node 1 have degree 2. Therefore, its score is 1.
Node 2 have degree 1. Therefore, its score is 0.
Node 3 have degree 1. Therefore, its score is 0.
Therefore, total score = 1 + 0 + 0 = 1.



Naive Approach: The simplest approach is to generate all possible combinations of constructing a tree having N nodes and find the total score for each of them. Then, print the maximum of all the scores obtained. 

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

Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming by creating a dp[][] table where dp[i][j] represents the maximum score using i nodes having the sum of degrees of the nodes as j. Follow the below steps to solve the problem:

dp[i][s] = max(dp[i][s], scores[j-1] dp[i-1][s-j])
where dp[i][s] represents the maximum score of tree having i nodes and sum of degrees as s.

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum score
// for one possible tree having N nodes
// N - 1 Edges
int maxScore(vector<int>& arr)
{
    int N = arr.size();
 
    // Number of nodes
    N++;
 
    // Initialize dp[][]
    vector<vector<int> >
        dp(N + 1, vector<int>(2 * N,
                              -100000));
 
    // Score with 0 vertices is 0
    dp[0][0] = 0;
 
    // Traverse the nodes from 1 to N
    for (int i = 1; i <= N; i++) {
 
        // Find maximum scores for
        // each sum
        for (int s = 1;
             s <= 2 * (N - 1); s++) {
 
            // Iterate over degree of
            // new node
            for (int j = 1; j <= N - 1
                            and j <= s;
                 j++) {
 
                // Update the current
                // state
                dp[i][s]
                    = max(dp[i][s],
                          arr[j - 1]
                              + dp[i - 1][s - j]);
            }
        }
    }
 
    // Return maximum score for N node
    // tree having 2(N - 1) sum of degree
    return dp[N][2 * (N - 1)];
}
 
// Driver Code
int main()
{
    // Given array of scores
    vector<int> arr = { 1, 3, 0 };
 
    // Function Call
    cout << maxScore(arr);
 
    return 0;
}




// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find the maximum score
// for one possible tree having N nodes
// N - 1 Edges
static int maxScore(int[] arr)
{
    int N = arr.length;
 
    // Number of nodes
    N++;
 
    // Initialize dp[][]
    int [][] dp = new int[N + 1][2 * (N - 1) + 1];
     
    // Score with 0 vertices is 0
    dp[0][0] = 0;
 
    // Traverse the nodes from 1 to N
    for(int i = 1; i <= N; i++)
    {
         
        // Find maximum scores for
        // each sum
        for(int s = 1; s <= 2 * (N - 1); s++)
        {
             
            // Iterate over degree of
            // new node
            for(int j = 1; j <= N - 1 && j <= s; j++)
            {
                 
                // Update the current
                // state
                dp[i][s] = Math.max(dp[i][s],
                                   arr[j - 1] +
                                    dp[i - 1][s - j]);
            }
        }
    }
 
    // Return maximum score for N node
    // tree having 2(N - 1) sum of degree
    return dp[N][2 * (N - 1)] - 1;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Given array of scores
    int [] arr = { 1, 3, 0 };
 
    // Function Call
    System.out.print(maxScore(arr));
}
}
 
// This code is contributed by Amit Katiyar




# Python3 program for the above approach
 
# Function to find the maximum score
# for one possible tree having N nodes
# N - 1 Edges
def maxScore(arr):
     
    N = len(arr)
 
    # Number of nodes
    N += 1
 
    # Initialize dp[][]
    dp = [[-100000 for i in range(2 * N)]
                   for i in range(N + 1)]
 
    # Score with 0 vertices is 0
    dp[0][0] = 0
 
    # Traverse the nodes from 1 to N
    for i in range(1, N + 1):
         
        # Find maximum scores for
        # each sum
        for s in range(1, 2 * (N - 1) + 1):
             
            # Iterate over degree of
            # new node
            j = 1
            while j <= N - 1 and j <= s:
                 
                # Update the current
                # state
                dp[i][s] = max(dp[i][s], arr[j - 1] +
                               dp[i - 1][s - j])
                j += 1
                 
    # Return maximum score for N node
    # tree having 2(N - 1) sum of degree
    return dp[N][2 * (N - 1)]
 
# Driver Code
if __name__ == '__main__':
     
    # Given array of scores
    arr = [ 1, 3, 0 ]
 
    # Function Call
    print(maxScore(arr))
 
# This code is contributed by mohit kumar 29




// C# program for the
// above approach
using System;
class GFG{
 
// Function to find the
// maximum score for one
// possible tree having N
// nodes N - 1 Edges
static int maxScore(int[] arr)
{
  int N = arr.Length;
 
  // Number of nodes
  N++;
 
  // Initialize [,]dp
  int [,] dp = new int[N + 1,
                       2 * (N -
                       1) + 1];
 
  // Score with 0 vertices
  // is 0
  dp[0, 0] = 0;
 
  // Traverse the nodes from
  // 1 to N
  for(int i = 1; i <= N; i++)
  {
    // Find maximum scores for
    // each sum
    for(int s = 1;
            s <= 2 * (N - 1); s++)
    {
      // Iterate over degree of
      // new node
      for(int j = 1;
              j <= N - 1 && j <= s; j++)
      {
        // Update the current
        // state
        dp[i, s] = Math.Max(dp[i, s],
                            arr[j - 1] +
                            dp[i - 1,
                               s - j]);
      }
    }
  }
 
  // Return maximum score for
  // N node tree having 2(N - 1)
  // sum of degree
  return dp[N, 2 * (N -
            1)] - 1;
}
 
// Driver Code
public static void Main(String[] args)
{   
  // Given array of scores
  int [] arr = {1, 3, 0};
 
  // Function Call
  Console.Write(maxScore(arr));
}
}
 
// This code is contributed by Princi Singh




<script>
  
// Javascript program for the above approach
 
// Function to find the maximum score
// for one possible tree having N nodes
// N - 1 Edges
function maxScore(arr)
{
    var N = arr.length;
 
    // Number of nodes
    N++;
 
    // Initialize dp[][]
    var dp = Array.from(Array(N+1), ()=> Array(2*N).fill(-10000000));
 
    // Score with 0 vertices is 0
    dp[0][0] = 0;
 
    // Traverse the nodes from 1 to N
    for (var i = 1; i <= N; i++) {
 
        // Find maximum scores for
        // each sum
        for (var s = 1;
             s <= 2 * (N - 1); s++) {
 
            // Iterate over degree of
            // new node
            for (var j = 1; j <= N - 1
                            && j <= s;
                 j++) {
 
                // Update the current
                // state
                dp[i][s]
                    = Math.max(dp[i][s],
                          arr[j - 1]
                              + dp[i - 1][s - j]);
            }
        }
    }
 
    // Return maximum score for N node
    // tree having 2(N - 1) sum of degree
    return dp[N][2 * (N - 1)];
}
 
// Driver Code
 
// Given array of scores
var arr = [1, 3, 0];
 
// Function Call
document.write( maxScore(arr));
 
</script>

Output
8

Time Complexity: O(N3)
Auxiliary Space: O(N2)

Efficient Approach : Space optimization

we have eliminated the use of unnecessary rows in the dp array and used only two rows (one for the current iteration and one for the previous iteration) to store the values. We have also replaced the dp[i][s] with dp[curr][s] and dp[i-1][s-j] with dp[prev][s-j] to further reduce memory usage.

Implementation Steps:

Implementation:




// C++ program for above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum score
// for one possible tree having N nodes
// N - 1 Edges
int maxScore(vector<int>& arr) {
    int N = arr.size();
       // Number of nodes
    N++;
       
      // initialize Dp of Two rows only to keep track
    // of current and previous row computations
    vector<vector<int>> dp(2, vector<int>(2 * N, -100000));
       
    // Base Case   
    dp[0][0] = 0;
   
      // iterate over subproblems to get the current value
    for (int i = 1; i <= N; i++) {
          // current value and previous value
        int curr = i % 2, prev = (i - 1) % 2;
        for (int s = 1; s <= 2 * (N - 1); s++) {
               
              // update current index of DP with minimum value
            dp[curr][s] = -100000;
     
            for (int j = 1; j <= N - 1 and j <= s; j++) {
               
                  // store answer in DP get from current and previous row
                dp[curr][s] = max(dp[curr][s], arr[j - 1] + dp[prev][s - j]);
            }
        }
    }
   
      // return answer
    return dp[N % 2][2 * (N - 1)];
}
 
// Driver code
 
int main() {
    vector<int> arr = { 1, 3, 0 };
   
   // Function call
    cout << maxScore(arr);
    return 0;
}
 
// this code is contributed by bhardwajji




import java.util.*;
 
public class Main {
    // Function to find the maximum score
    // for one possible tree having N nodes
    // N - 1 Edges
    public static int maxScore(List<Integer> arr) {
        int N = arr.size();
        // Number of nodes
        N++;
           
        // initialize Dp of Two rows only to keep track
        // of current and previous row computations
        List<List<Integer>> dp = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            List<Integer> row = new ArrayList<>();
            for (int j = 0; j < 2 * N; j++) {
                row.add(-100000);
            }
            dp.add(row);
        }
           
        // Base Case   
        dp.get(0).set(0, 0);
       
        // iterate over subproblems to get the current value
        for (int i = 1; i <= N; i++) {
            // current value and previous value
            int curr = i % 2, prev = (i - 1) % 2;
            for (int s = 1; s <= 2 * (N - 1); s++) {
                   
                // update current index of DP with minimum value
                dp.get(curr).set(s, -100000);
         
                for (int j = 1; j <= N - 1 && j <= s; j++) {
                       
                    // store answer in DP get from current and previous row
                    dp.get(curr).set(s, Math.max(dp.get(curr).get(s), arr.get(j - 1) + dp.get(prev).get(s - j)));
                }
            }
        }
       
        // return answer
        return dp.get(N % 2).get(2 * (N - 1));
    }
       
    // Driver code
    public static void main(String[] args) {
        List<Integer> arr = new ArrayList<>(Arrays.asList(1, 3, 0));
           
        // Function call
        System.out.println(maxScore(arr));
    }
}




using System;
 
public class Program
{
 
  // Function to find the maximum score
  // for one possible tree having N nodes
  // N - 1 Edges
  public static int maxScore(int[] arr)
  {
    int N = arr.Length;
 
    // Number of nodes
    N++;
 
    // initialize Dp of Two rows only to keep track
    // of current and previous row computations
    int[][] dp = new int[2][];
    dp[0] = new int[2 * N];
    dp[1] = new int[2 * N];
    for (int i = 0; i < 2 * N; i++) {
      dp[0][i] = -100000;
      dp[1][i] = -100000;
    }
 
    // Base Case
    dp[0][0] = 0;
 
    // iterate over subproblems to get the current value
    for (int i = 1; i <= N; i++)
    {
 
      // current value and previous value
      int curr = i % 2, prev = (i - 1) % 2;
      for (int s = 1; s <= 2 * (N - 1); s++) {
 
        // update current index of DP with minimum
        // value
        dp[curr][s] = -100000;
 
        for (int j = 1; j <= N - 1 && j <= s; j++) {
 
          // store answer in DP get from current
          // and previous row
          dp[curr][s] = Math.Max(
            dp[curr][s],
            arr[j - 1] + dp[prev][s - j]);
        }
      }
    }
 
    // return answer
    return dp[N % 2][2 * (N - 1)];
  }
 
  // Driver code
  public static void Main()
  {
    int[] arr = { 1, 3, 0 };
 
    // Function call
    Console.WriteLine(maxScore(arr));
  }
}
 
// This code is contributed by Prajwal Kandekar




def maxScore(arr):
    N = len(arr)
    # Number of nodes
    N += 1
       
    # initialize Dp of Two rows only to keep track
    # of current and previous row computations
    dp = [[-100000] * (2 * N) for i in range(2)]
           
    # Base Case   
    dp[0][0] = 0
       
    # iterate over subproblems to get the current value
    for i in range(1, N + 1):
        # current value and previous value
        curr = i % 2
        prev = (i - 1) % 2
        for s in range(1, 2 * (N - 1) + 1):
            # update current index of DP with minimum value
            dp[curr][s] = -100000
         
            for j in range(1, N) :
                if j <= s:
                    # store answer in DP get from current and previous row
                    dp[curr][s] = max(dp[curr][s], arr[j - 1] + dp[prev][s - j])
       
    # return answer
    return dp[N % 2][2 * (N - 1)]
 
# Driver code
arr = [1, 3, 0]
# Function call
print(maxScore(arr))




// Javascript code addition
 
function maxScore(arr) {
  let N = arr.length;
  // Number of nodes
  N++;
 
  // initialize Dp of Two rows only to keep track
  // of current and previous row computations
  let dp = new Array(2).fill(null).map(() => new Array(2 * N).fill(-100000));
 
  // Base Case   
  dp[0][0] = 0;
 
  // iterate over subproblems to get the current value
  for (let i = 1; i <= N; i++) {
    // current value and previous value
    let curr = i % 2;
    let prev = (i - 1) % 2;
 
    for (let s = 1; s <= 2 * (N - 1); s++) {
      // update current index of DP with minimum value
      dp[curr][s] = -100000;
 
      for (let j = 1; j <= N - 1 && j <= s; j++) {
        // store answer in DP get from current and previous row
        dp[curr][s] = Math.max(dp[curr][s], arr[j - 1] + dp[prev][s - j]);
      }
    }
  }
 
  // return answer
  return dp[N % 2][2 * (N - 1)];
}
 
// Driver code
let arr = [1, 3, 0];
// Function call
console.log(maxScore(arr));
 
// The code is contributed by Nidhi goel.

Output
8

Time Complexity: O(N*N*N)
Auxiliary Space: O(N) or O(N*2)


Article Tags :