Skip to content
Related Articles

Related Articles

Minimize deletion of edges to convert Tree into a forest of size at most N/2

View Discussion
Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 01 Jul, 2022
View Discussion
Improve Article
Save Article

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


Output

2

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


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!