Minimize deletion of edges to convert Tree into a forest of size at most N/2
Given a tree with N nodes, numbered from 0 to N – 1, the task is to find the minimum number of deletion of edges, such that, the tree is converted into a forest where each tree in the forest can have size less than equal to ⌊N/2⌋.
Examples:
Input: N = 3, edges = [[0, 1], [0, 2]]
0
/ \
1 2
Output: 2
Explanation: The maximum size of each tree after removing the edges can be 1.
So every node has to be separated from each other.
So, remove all the 2 edges present in the tree.
Hence, the answer will be 2.Input: N = 7, edges = [[0, 1], [1, 2], [1, 3], [0, 4], [4, 5], [4, 6]]
0
/ \
1 4
/ \ / \
2 3 5 6
Output: 2
Explanation: Remove the edges (0 – 1) and (0 – 4) to satisfy the condition. Hence, the answer will be 2.
Approach: The idea to solve the problem is using Depth First Search.
Follow the steps to solve the given problem:
- Create the graph from the given input.
- Calculate the centroids using the dfs function.
- If the tree has two centroids, then the answer will be 1.
- Else, declare a vector subtreeSize, which will calculate the subtree size of all the children of the centroid.
- Calculate the subtree sizes using the dfs2 function.
- Declare two variables, ans and sum, to store the answer and the number of nodes removed due to the removal of edges.
- Sort the subtreeSize in descending order.
- Iterate over the subtreeSize vector.
- Add the current value to the sum and increase the ans by 1.
- If the remaining nodes are less than or equal to N/ 2
- Break the loop.
- Finally, return the ans.
Below is the implementation of the above approach :
C++
// C++ Code for the above approach: #include <bits/stdc++.h> using namespace std; // Function to calculate the // Centroids of the tree. void dfs( int n, int par, vector< int >* ar, vector< int >& size, int & cent1, int & cent2, int & some, int tot) { size[n] = 1; int mx = 0; // Iterate through the children // of the current node and // store the maximum of the subtree size // among the children in the mx variable. for ( int child : ar[n]) { if (child != par) { dfs(child, n, ar, size, cent1, cent2, some, tot); size[n] += size[child]; mx = max(mx, size[child]); } } mx = max(mx, tot - size[n]); // If mx is smaller than the maximum // subtree size till now, // update that and centroids accordingly. if (mx < some) { some = mx; cent1 = n; cent2 = -1; } else if (mx == some) { cent2 = n; } } // Function to calculate the subtree // size of the given node. void dfs2( int n, int par, vector< int >* ar, int & val) { val++; for ( int child : ar[n]) { if (child != par) { dfs2(child, n, ar, val); } } } int minimumEdges( int n, vector<vector< int > >& edges) { vector< int > ar[n]; vector< int > size(n, 0); // Create the graph // From the given input. for ( int i = 0; i < n - 1; i++) { ar[edges[i][0]] .push_back(edges[i][1]); ar[edges[i][1]] .push_back(edges[i][0]); } int cent1 = -1, cent2 = -1, some = 1000000; // Calculate the centroids // Using the dfs function. dfs(0, -1, ar, size, cent1, cent2, some, n); // If the tree has two centroids, // Then the answer will be 1. if (cent2 != -1) { return 1; } // Declare a vector subtreeSize, // Which will calculate the // Subtree size of all the children // Of the centroid. vector< int > subtree_size; // Calculate the subtree sizes // Using the dfs2 function. for ( int x : ar[cent1]) { int val = 0; dfs2(x, cent1, ar, val); subtree_size.push_back(val); } // Declare two variables, ans and sum, // To store the answer // And the number of nodes removed // Due to the removal of edges. int sum = 0; int ans = 0; // Sort the subtreeSize // In descending order. sort(subtree_size.rbegin(), subtree_size.rend()); // Iterate over the “subtreeSize” vector. for ( int x : subtree_size) { // Add the current value to the sum // And increase the ans by 1. sum += x; ans++; // If the remaining nodes are // Less than or equal to N / 2, // Break the loop. if (n - sum <= n / 2) { break ; } } // Finally, return the ans. return ans; } // Driver code int main() { int N = 3; vector<vector< int > > edges = { { 0, 1 }, { 0, 2 } }; cout << minimumEdges(N, edges) << "\n" ; return 0; } |
Java
// Java code for the above approach: import java.util.*; public class Main { static int cent1,cent2; static int [] size; static int val; // Function to calculate the // Centroids of the tree. static void dfs( int n, int par, ArrayList <ArrayList <Integer>> ar, int some, int tot) { size[n] = 1 ; int mx = 0 ; // Iterate through the children // of the current node and // store the maximum of the subtree size // among the children in the mx variable. for ( int child : ar.get(n)) { if (child != par) { dfs(child, n, ar, some, tot); size[n] += size[child]; mx = Math.max(mx, size[child]); } } mx = Math.max(mx, tot - size[n]); // If mx is smaller than the maximum // subtree size till now, // update that and centroids accordingly. if (mx < some) { some = mx; cent1 = n; cent2 = - 1 ; } else if (mx == some) { cent2 = n; } } // Function to calculate the subtree // size of the given node. static void dfs2( int n, int par, ArrayList <ArrayList<Integer>> ar) { val++; for ( int child : ar.get(n)) { if (child != par) { dfs2(child, n, ar); } } } static int minimumEdges( int n, int [][] edges) { ArrayList <ArrayList <Integer>> ar = new ArrayList <ArrayList<Integer>> (n); for ( int i= 0 ; i<n; i++){ ar.add( new ArrayList <Integer> () ); } size = new int [n]; Arrays.fill(size, 0 ); // Create the graph // From the given input. for ( int i = 0 ; i < n - 1 ; i++) { ar.get(edges[i][ 0 ]) .add(edges[i][ 1 ]); ar.get(edges[i][ 1 ]) .add(edges[i][ 0 ]); } cent1 = - 1 ; cent2 = - 1 ; int some = 1000000 ; // Calculate the centroids // Using the dfs function. dfs( 0 , - 1 , ar, some, n); // If the tree has two centroids, // Then the answer will be 1. if (cent2 != - 1 ) { return 1 ; } // Declare a vector subtreeSize, // Which will calculate the // Subtree size of all the children // Of the centroid. ArrayList <Integer> subtree_size = new ArrayList <Integer> (); // Calculate the subtree sizes // Using the dfs2 function. for ( int x : ar.get(cent1) ) { val = 0 ; dfs2(x, cent1, ar); subtree_size.add(val); } // Declare two variables, ans and sum, // To store the answer // And the number of nodes removed // Due to the removal of edges. int sum = 0 ; int ans = 0 ; // Sort the subtreeSize // In descending order. Collections.sort(subtree_size); // Iterate over the “subtreeSize” vector. for ( int x : subtree_size) { // Add the current value to the sum // And increase the ans by 1. sum += x; ans++; // If the remaining nodes are // Less than or equal to N / 2, // Break the loop. if (n - sum <= n / 2 ) { break ; } } // Finally, return the ans. return ans; } // Driver Code public static void main(String args[]) { int N = 3 ; int [][] edges = { { 0 , 1 }, { 0 , 2 } }; // Function call System.out.println( minimumEdges(N, edges) ); } } // This code has been contributed by Sachin Sahara (sachin801) |
Python3
## Function to calculate the ## Centroids of the tree. def dfs(n, par, ar, size, lis, tot) : size[n] = 1 mx = 0 ## Iterate through the children ## of the current node and ## store the maximum of the subtree size ## among the children in the mx variable. for child in ar[n]: if (child ! = par): dfs(child, n, ar, size, lis, tot) size[n] + = size[child] mx = max (mx, size[child]) mx = max (mx, tot - size[n]); ## If mx is smaller than the maximum ## subtree size till now, ## update that and centroids accordingly. if (mx < lis[ 2 ]): lis[ 2 ] = mx; lis[ 0 ] = n; lis[ 1 ] = - 1 ; elif (mx = = lis[ 2 ]): lis[ 1 ] = n; ## Function to calculate the subtree ## size of the given node. def dfs2(n, par, ar, val): val = 1 for child in ar[n]: if (child ! = par): val + = dfs2(child, n, ar, val) return val def minimumEdges(n, edges): ar = [] size = [] for i in range (n): ar.append( list ()) size.append( 0 ) ## Create the graph ## From the given input. for i in range (n - 1 ): ar[edges[i][ 0 ]].append(edges[i][ 1 ]) ar[edges[i][ 1 ]].append(edges[i][ 0 ]) cent1 = - 1 cent2 = - 1 some = 1000000 lis = [ - 1 , - 1 , 1000000 ] ## Calculate the centroids ## Using the dfs function. dfs( 0 , - 1 , ar, size, lis, n); cent1 = lis[ 0 ] cent2 = lis[ 1 ] some = lis[ 2 ] ## If the tree has two centroids, ## Then the answer will be 1. if (cent2 ! = - 1 ): return 1 ## Declare a vector subtreeSize, ## Which will calculate the ## Subtree size of all the children ## Of the centroid. subtree_size = [] ## Calculate the subtree sizes ## Using the dfs2 function. for x in ar[cent1]: val = 0 val = dfs2(x, cent1, ar, val) subtree_size.append(val) ## Declare two variables, ans and sum, ## To store the answer ## And the number of nodes removed ## Due to the removal of edges. sum = 0 ans = 0 ## Sort the subtreeSize ## In descending order. subtree_size.sort() ## Iterate over the “subtreeSize” vector. for x in subtree_size: ## Add the current value to the sum ## And increase the ans by 1. sum + = x ans + = 1 ## If the remaining nodes are ## Less than or equal to N / 2, ## Break the loop. if (n - sum < = n / 2 ): break ; return ans # Driver Code if __name__ = = "__main__" : N = 3 edges = list (( list (( 0 , 1 )), list (( 0 , 2 )))) print (minimumEdges(N, edges)) # This code is contributed by subhamgoyal2014. |
C#
// C# code for the above approach: using System; using System.Collections.Generic; public class GFG { static int cent1,cent2; static int [] size; static int val; // Function to calculate the // Centroids of the tree. static void dfs( int n, int par, List <List < int >> ar, int some, int tot) { size[n] = 1; int mx = 0; // Iterate through the children // of the current node and // store the maximum of the subtree size // among the children in the mx variable. foreach ( int child in ar[n]) { if (child != par) { dfs(child, n, ar, some, tot); size[n] += size[child]; mx = Math.Max(mx, size[child]); } } mx = Math.Max(mx, tot - size[n]); // If mx is smaller than the maximum // subtree size till now, // update that and centroids accordingly. if (mx < some) { some = mx; cent1 = n; cent2 = -1; } else if (mx == some) { cent2 = n; } } // Function to calculate the subtree // size of the given node. static void dfs2( int n, int par, List <List< int >> ar) { val++; foreach ( int child in ar[n]) { if (child != par) { dfs2(child, n, ar); } } } static int minimumEdges( int n, int [,] edges) { List <List < int >> ar = new List <List< int >> (n); for ( int i=0; i<n; i++){ ar.Add( new List < int > () ); } size = new int [n]; // Arrays.fill(size, 0); // Create the graph // From the given input. for ( int i = 0; i < n - 1; i++) { ar[edges[i,0]] .Add(edges[i,1]); ar[edges[i,1]] .Add(edges[i,0]); } cent1 = -1; cent2 = -1; int some = 1000000; // Calculate the centroids // Using the dfs function. dfs(0, -1, ar, some, n); // If the tree has two centroids, // Then the answer will be 1. if (cent2 != -1) { return 1; } // Declare a vector subtreeSize, // Which will calculate the // Subtree size of all the children // Of the centroid. List < int > subtree_size = new List < int > (); // Calculate the subtree sizes // Using the dfs2 function. foreach ( int x in ar[cent1] ) { val = 0; dfs2(x, cent1, ar); subtree_size.Add(val); } // Declare two variables, ans and sum, // To store the answer // And the number of nodes removed // Due to the removal of edges. int sum = 0; int ans = 0; // Sort the subtreeSize // In descending order. subtree_size.Sort(); // Iterate over the “subtreeSize�? vector. foreach ( int x in subtree_size) { // Add the current value to the sum // And increase the ans by 1. sum += x; ans++; // If the remaining nodes are // Less than or equal to N / 2, // Break the loop. if (n - sum <= n / 2) { break ; } } // Finally, return the ans. return ans; } // Driver Code public static void Main(String []args) { int N = 3; int [,] edges = { { 0, 1 }, { 0, 2 } }; // Function call Console.WriteLine( minimumEdges(N, edges) ); } } // This code is contributed by shikhasingrajput |
Javascript
<script> // JavaScript code for the above approach // Function to calculate the // Centroids of the tree. function dfs(n, par, ar, some, tot) { size[n] = 1; let mx = 0; // Iterate through the children // of the current node and // store the maximum of the subtree size // among the children in the mx variable. for ( var child of ar[n]) { if (child !== par) { dfs(child, n, ar, some, tot); size[n] += size[child]; mx = Math.max(mx, size[child]); } } mx = Math.max(mx, tot - size[n]); // If mx is smaller than the maximum // subtree size till now, // update that and centroids accordingly. if (mx < some) { some = mx; cent1 = n; cent2 = -1; } else if (mx === some) { cent2 = n; } } // Function to calculate the subtree // size of the given node. function dfs2(n, par, ar) { val++; for ( var child of ar[n]) { if (child !== par) { dfs2(child, n, ar); } } } function minimumEdges(n, edges) { var ar = new Array(n); for (let i = 0; i < n; i++) { ar[i] = []; } size = new Array(n).fill(0); // Create the graph // From the given input. for (let i = 0; i < n - 1; i++) { ar[edges[i][0]].push(edges[i][1]); ar[edges[i][1]].push(edges[i][0]); } cent1 = -1; cent2 = -1; var some = 1000000; // Calculate the centroids // Using the dfs function. dfs(0, -1, ar, some, n); // If the tree has two centroids, // Then the answer will be 1. if (cent2 !== -1) { return 1; } // Declare a vector subtreeSize, // Which will calculate the // Subtree size of all the children // Of the centroid. var subtreeSize = []; // Calculate the subtree sizes // Using the dfs2 function. for ( var x of ar[cent1]) { val = 0; dfs2(x, cent1, ar); subtreeSize.push(val); } // Declare two variables, ans and sum, // To store the answer // And the number of nodes removed // Due to the removal of edges. let sum = 0; let ans = 0; // Sort the subtreeSize // In descending order subtreeSize.sort((a, b) => b - a); for (let x of subtreeSize) { sum += x; ans++; if (n - sum <= n / 2) { break ; } } return ans; } //Driver Code let N = 3; let edges = [[0, 1], [0, 2]]; document.write(minimumEdges(N, edges)); // This code is contributed by Potta Lokesh </script> |
2
Time Complexity: O(N * log(N))
Auxiliary Space: O(N)
Please Login to comment...