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:
- Initialize an array dp[N + 1][2*(N – 1) + 1] where N is the number of nodes and (2*(N – 1)) is the maximum sum of degrees.
- Initialize dp[0][0] with 0.
- Iterate two nested loops, one over the range [1, N], and another for till the possible maximum score 2*(N – 1) from 1 and for each score s in the range [1, N] traverse the given array of scores arr[] and updating dp[i][s] as:
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.
- For a tree with N vertices and (N – 1) edges, the sum of all degrees should be 2 * (N – 1). Therefore, print the value of dp[N][2*(N – 1)] as the maximum score for a tree with N nodes.
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> |
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:
- Create a DP vector table of 2 rows to only determine current and previous computations.
- Initialize DP with -100000 because we are finding a maximum value to update DP.
- Now Iterate over subproblems through nested loops and get the computation of current problem from previous and current row of DP.
- At last return answer store in dp[N % 2][2 * (N – 1)].
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. |
8
Time Complexity: O(N*N*N)
Auxiliary Space: O(N) or O(N*2)