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++ 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 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) |
## 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# 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 |
<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)