Given an integer L which is the sum of degrees of all the vertices of some tree. The task is to find the count of all such distinct trees (labeled trees). Two trees are distinct if they have at least a single different edge.
Examples:
Input: L = 2
Output: 1
Input: L = 6
Output: 16
Simple Solution: A simple solution is to find the number of nodes of the tree which has sum of degrees of all vertices as L. Number of nodes in such a tree is n = (L / 2 + 1) as described in this article.
Now the solution is to form all the labeled trees which can be formed using n nodes. This approach is quite complex and for larger values of n it is not possible to find out the number of trees using this process.
Efficient Solution: An efficient solution is to find the number of nodes using Cayley’s formula which states that there are n(n – 2) trees with n labeled vertices. So the time complexity of the code now reduces to O(n) which can be further reduced to O(logn) using modular exponentiation.
Below is the implementation of the above approach:
// C++ implementation of the approach #include <iostream> using namespace std;
#define ll long long int // Iterative Function to calculate (x^y) in O(log y) ll power( int x, ll y)
{ // Initialize result
ll res = 1;
while (y > 0) {
// If y is odd, multiply x with result
if (y & 1)
res = (res * x);
// y must be even now
// y = y / 2
y = y >> 1;
x = (x * x);
}
return res;
} // Function to return the count // of required trees ll solve( int L)
{ // number of nodes
int n = L / 2 + 1;
ll ans = power(n, n - 2);
// Return the result
return ans;
} // Driver code int main()
{ int L = 6;
cout << solve(L);
return 0;
} |
// Java implementation of the approach import java.io.*;
class GFG
{ // Iterative Function to calculate (x^y) in O(log y) static long power( int x, long y)
{ // Initialize result
long res = 1 ;
while (y > 0 )
{
// If y is odd, multiply x with result
if (y== 1 )
res = (res * x);
// y must be even now
// y = y / 2
y = y >> 1 ;
x = (x * x);
}
return res;
} // Function to return the count // of required trees static long solve( int L)
{ // number of nodes
int n = L / 2 + 1 ;
long ans = power(n, n - 2 );
// Return the result
return ans;
} // Driver code public static void main (String[] args)
{ int L = 6 ;
System.out.println (solve(L));
} } // This code is contributed by ajit. |
# Python implementation of the approach # Iterative Function to calculate (x^y) in O(log y) def power(x, y):
# Initialize result
res = 1 ;
while (y > 0 ):
# If y is odd, multiply x with result
if (y % 2 = = 1 ):
res = (res * x);
# y must be even now
#y = y / 2
y = int (y) >> 1 ;
x = (x * x);
return res;
# Function to return the count # of required trees def solve(L):
# number of nodes
n = L / 2 + 1 ;
ans = power(n, n - 2 );
# Return the result
return int (ans);
L = 6 ;
print (solve(L));
# This code has been contributed by 29AjayKumar |
// C# implementation of the approach using System;
class GFG
{ // Iterative Function to calculate (x^y) in O(log y) static long power( int x, long y)
{ // Initialize result
long res = 1;
while (y > 0)
{
// If y is odd, multiply x with result
if (y == 1)
res = (res * x);
// y must be even now
// y = y / 2
y = y >> 1;
x = (x * x);
}
return res;
} // Function to return the count // of required trees static long solve( int L)
{ // number of nodes
int n = L / 2 + 1;
long ans = power(n, n - 2);
// Return the result
return ans;
} // Driver code static public void Main ()
{ int L = 6;
Console.WriteLine(solve(L));
} } // This code is contributed by Tushil. |
<script> // Javascript implementation of the approach // Iterative Function to calculate (x^y) in O(log y) function power(x, y)
{ // Initialize result
var res = 1;
while (y > 0) {
// If y is odd, multiply x with result
if (y & 1)
res = (res * x);
// y must be even now
// y = y / 2
y = y >> 1;
x = (x * x);
}
return res;
} // Function to return the count // of required trees function solve(L)
{ // number of nodes
var n = L / 2 + 1;
var ans = power(n, n - 2);
// Return the result
return ans;
} // Driver code var L = 6;
document.write( solve(L)); // This code is contributed by rutvik_56. </script> |
16
Time Complexity : O(logn)
Auxiliary Space: O(1)
Approach(Using recursion): Another approach to count trees with a given sum of degrees is to use recursion.
Algorithm:
- Define a recursive function that takes two arguments: n (the number of vertices in the tree) and L (the sum of degrees of all vertices).
-
Add the two base cases:
a. If n is 1 and L is 0 then return 1 (since a tree with one vertex has degree 0).
b. If n is greater than 1 and L is equal to 2(n-1) then return n^(n-2) (since this is the number of labeled trees with n vertices and sum of degrees L). - For all other values of n and L, iterate over all possible degrees d in the range [1, L-1] (since the degree of a vertex in a tree must be at least 1 and at most L-1) and for each value of d, recursively compute the number of trees with d vertices and the sum of degrees L-d on the left subtree is the number of trees with n-d vertices and sum of degrees d-1 on the right subtree.
- Multiply the number of trees on the left subtree by the number of trees on the right subtree, and add the result to the running total and return the running total as the answer.
Below is the implementation of above approach.
#include <iostream> using namespace std;
#define ll long long int // Recursive Function to calculate (x^y) in O(log y) ll power( int x, ll y)
{ if (y == 0) {
return 1;
} else if (y % 2 == 0) {
ll temp = power(x, y / 2);
return temp * temp;
} else {
ll temp = power(x, y / 2);
return x * temp * temp;
}
} // Recursive function to return the count of required trees ll countTrees( int n, int L)
{ // Base case: a tree with one vertex has degree 0
if (n == 1 && L == 0) {
return 1;
}
// Base case: a tree with n vertices has sum of degrees 2(n-1)
if (n > 1 && L == 2 * (n - 1)) {
return power(n, n - 2);
}
ll ans = 0;
// Consider the last vertex in the tree, with degree d in the range [1, L-1]
for ( int d = 1; d <= min(L - 1, n - 1); d++) {
// Recursively compute the number of trees for each possible value of d
ll leftCount = countTrees(d, L - d);
ll rightCount = countTrees(n - d, d - 1);
ans += leftCount * rightCount;
}
return ans;
} // Driver code int main()
{ int L = 6;
int n = L / 2 + 1;
cout << countTrees(n, L);
return 0;
} |
import java.util.*;
public class Main {
public static void main(String[] args) {
int L = 6 ;
int n = L / 2 + 1 ;
System.out.println(countTrees(n, L));
}
// Recursive function to calculate the power of a number
public static long power( int x, long y) {
if (y == 0 ) {
return 1 ;
} else if (y % 2 == 0 ) {
// If y is even, use recursion to calculate x^(y/2) and square it
long temp = power(x, y / 2 );
return temp * temp;
} else {
// If y is odd, use recursion to calculate x^(y/2) and multiply it with x and square it
long temp = power(x, y / 2 );
return x * temp * temp;
}
}
// Recursive function to count the number of unique binary trees that can be formed with n nodes and L levels
public static long countTrees( int n, int L) {
// Base case: if we have a single node and no levels (empty tree), there is one possible tree
if (n == 1 && L == 0 ) {
return 1 ;
}
// If the tree consists of n nodes and each node has exactly two children, and it has L levels, there's a unique solution.
if (n > 1 && L == 2 * (n - 1 )) {
// In this case, the number of unique trees can be calculated as n^(n-2)
return power(n, n - 2 );
}
long ans = 0 ;
// Try all possible left subtree sizes (d) from 1 to the minimum of (L-1) and (n-1)
for ( int d = 1 ; d <= Math.min(L - 1 , n - 1 ); d++) {
// Count the number of unique left subtrees with 'd' nodes and remaining 'L-d' levels
long leftCount = countTrees(d, L - d);
// Count the number of unique right subtrees with 'n-d' nodes and 'd-1' levels
long rightCount = countTrees(n - d, d - 1 );
// For each combination of left and right subtrees, add their counts to the total count 'ans'
ans += leftCount * rightCount;
}
return ans;
}
} |
# Function to calculate the power of a number (x^y) in O(log y) def power(x, y):
if y = = 0 :
return 1
elif y % 2 = = 0 :
# If y is even, calculate power(x, y // 2) and square it
temp = power(x, y / / 2 )
return temp * temp
else :
# If y is odd, calculate power(x, y // 2) and multiply
# it with x and square it
temp = power(x, y / / 2 )
return x * temp * temp
# Recursive function to count the number of trees with n # vertices and a given sum of degrees L def count_trees(n, L):
# Base case: a tree with one vertex has degree 0
if n = = 1 and L = = 0 :
return 1
# Base case: a tree with n vertices has sum of degrees 2(n-1)
if n > 1 and L = = 2 * (n - 1 ):
return power(n, n - 2 )
ans = 0
# Consider the last vertex in the tree, with degree d in
# the range [1, L-1]
for d in range ( 1 , min (L - 1 , n - 1 ) + 1 ):
# Recursively compute the number of trees for each possible
# value of d
left_count = count_trees(d, L - d)
right_count = count_trees(n - d, d - 1 )
ans + = left_count * right_count
return ans
# Driver code if __name__ = = "__main__" :
L = 6
n = L / / 2 + 1
result = count_trees(n, L)
print ( result)
|
using System;
public class GFG {
// Recursive Function to calculate (x^y) in O(log y)
static long Power( int x, long y)
{
if (y == 0) {
return 1;
}
else if (y % 2 == 0) {
long temp = Power(x, y / 2);
return temp * temp;
}
else {
long temp = Power(x, y / 2);
return x * temp * temp;
}
}
// Recursive function to return the count of required
// trees
static long CountTrees( int n, int L)
{
// Base case: a tree with one vertex has degree 0
if (n == 1 && L == 0) {
return 1;
}
// Base case: a tree with n vertices has sum of
// degrees 2(n-1)
if (n > 1 && L == 2 * (n - 1)) {
return Power(n, n - 2);
}
long ans = 0;
// Consider the last vertex in the tree, with degree
// d in the range [1, L-1]
for ( int d = 1; d <= Math.Min(L - 1, n - 1); d++) {
// Recursively compute the number of trees for
// each possible value of d
long leftCount = CountTrees(d, L - d);
long rightCount = CountTrees(n - d, d - 1);
ans += leftCount * rightCount;
}
return ans;
}
// Driver code
public static void Main()
{
int L = 6;
int n = L / 2 + 1;
Console.WriteLine(CountTrees(n, L));
}
} |
// Recursive Function to calculate (x^y) in O(log y) function power(x, y) {
if (y === 0) {
return 1;
} else if (y % 2 === 0) {
let temp = power(x, y / 2);
return temp * temp;
} else {
let temp = power(x, Math.floor(y / 2));
return x * temp * temp;
}
} // Recursive function to return the count of required trees function countTrees(n, L) {
// Base case: a tree with one vertex has degree 0
if (n === 1 && L === 0) {
return 1;
}
// Base case: a tree with n vertices has sum of degrees 2(n-1)
if (n > 1 && L === 2 * (n - 1)) {
return power(n, n - 2);
}
let ans = 0;
// Consider the last vertex in the tree, with degree d in the range [1, L-1]
for (let d = 1; d <= Math.min(L - 1, n - 1); d++) {
// Recursively compute the number of trees for each possible value of d
let leftCount = countTrees(d, L - d);
let rightCount = countTrees(n - d, d - 1);
ans += leftCount * rightCount;
}
return ans;
} // Driver code function main() {
let L = 6;
let n = Math.floor(L / 2) + 1;
console.log(countTrees(n, L));
} main(); |
16
Time Complexity : O(n^(n-2)), since the number of distinct trees with n vertices is at most n^(n-2) (which is achieved when all vertices have degree 1).
Auxiliary Space: O(n), since each recursive call creates a new activation record on the stack, and the maximum depth of the recursion tree is n (which occurs when the sum of degrees is L = 2(n-1)).