Minimum number of Nodes to be removed such that no subtree has more than K nodes
Given a tree with N nodes value from 1 to N and (N – 1) Edges and a number K, the task is to remove the minimum number of nodes from the tree such that every subtree will have at most K nodes. Removing Nodes will remove the edges from that nodes to all the other connected nodes.
Examples:
Input: N = 10, K = 3, Below is the graph:
Output:
Number of nodes removed: 2
Removed Nodes: 2 1
Explanation:
After removing the nodes 1 and 2, here, no subtree or tree has more than 3 nodes. Below is the resulting graph:
Input: N = 6, K = 3, Below is the graph:
Output:
Number of nodes removed: 1
Removed Nodes: 1
Explanation:
After removing the nodes 1, here, no subtree or tree has more than 3 nodes. Below is the resulting graph:
Approach: The idea is to observe that the number of nodes in the subtree of a node X is the sum of the number of nodes in the subtree of its children and the node itself. Below are the steps:
- Use Dynamic Programming and DFS to store the count of nodes in the subtree of each node easily.
- Now, to have no node with subtree having more than K nodes, the idea is to remove the node whenever it has more than K nodes in its subtree, and pass 0 to its parent.
- In the above step, we are having each node with nodes in its subtree not greater than K and minimizing the number of node removals.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; #define N 20 // Function to perform DFS Traversal int dfs(vector< bool > &visited, int s, int &K, int &removals, vector< int > &removed_nodes, vector<vector< int >> &adj) { // Mark the node as true visited[s] = true ; int nodes = 1; // Traverse adjacency list // of child node for ( int child : adj[s]) { // If already visited then // omit the node if (visited[child]) continue ; // Add number of nodes // in subtree nodes += dfs(visited, child, K, removals, removed_nodes, adj); } if (nodes > K) { // Increment the count removals++; removed_nodes.push_back(s); nodes = 0; } // Return the nodes return nodes; } // Function to add edges in graph void addEdge(vector<vector< int >> &adj, int a, int b) { adj[a].push_back(b); adj[b].push_back(a); } // Function that finds the number // of nodes to be removed such that // every subtree has size at most K void findRemovedNodes(vector< bool > &visited, int K, int &removals, vector< int > &removed_nodes, vector<vector< int >> &adj) { // Function Call to find the // number of nodes to remove dfs(visited, 1, K, removals, removed_nodes, adj); // Print Removed Nodes cout << "Number of nodes removed: " << removals << endl; cout << "Removed Nodes: " ; for ( int node : removed_nodes) { cout << node << " " ; } } // Driver Code int main() { // Variables used to store data globally vector< bool > visited(N); int K; int removals = 0; vector< int > removed_nodes; // Adjacency list representation of tree vector<vector< int >> adj(N); // Insert of nodes in graph addEdge(adj, 1, 2); addEdge(adj, 1, 3); addEdge(adj, 2, 4); addEdge(adj, 2, 5); addEdge(adj, 3, 6); // Required subtree size K = 3; // Function Call findRemovedNodes(visited, K, removals, removed_nodes, adj); return 0; } // This code is contributed by sanjeev2552 |
Java
// Java program for the above approach import java.util.*; class GFG { // Variables used to store data globally static final int N = 20 ; static boolean visited[] = new boolean [N]; static int K; static int removals = 0 ; static ArrayList<Integer> removed_nodes = new ArrayList<>(); // Adjacency list representation of tree static ArrayList<ArrayList<Integer> > adj = new ArrayList<>(); // Function to perform DFS Traversal static int dfs( int s) { // Mark the node as true visited[s] = true ; int nodes = 1 ; // Traverse adjacency list // of child node for (Integer child : adj.get(s)) { // If already visited then // omit the node if (visited[child]) continue ; // Add number of nodes // in subtree nodes += dfs(child); } if (nodes > K) { // Increment the count removals++; removed_nodes.add(s); nodes = 0 ; } // Return the nodes return nodes; } // Function to add edges in graph static void addEdge( int a, int b) { adj.get(a).add(b); adj.get(b).add(a); } // Function that finds the number // of nodes to be removed such that // every subtree has size at most K public static void findRemovedNodes( int K) { // Function Call to find the // number of nodes to remove dfs( 1 ); // Print Removed Nodes System.out.println( "Number of nodes" + " removed: " + removals); System.out.print( "Removed Nodes: " ); for ( int node : removed_nodes) System.out.print(node + " " ); } // Driver Code public static void main(String[] args) { // Creating list for all nodes for ( int i = 0 ; i < N; i++) adj.add( new ArrayList<>()); // Insert of nodes in graph addEdge( 1 , 2 ); addEdge( 1 , 3 ); addEdge( 2 , 4 ); addEdge( 2 , 5 ); addEdge( 3 , 6 ); // Required subtree size K = 3 ; // Function Call findRemovedNodes(K); } } |
Python3
# Python3 program for the above approach # Variables used to store data globally N = 20 visited = [ False for i in range (N)] K = 0 removals = 0 removed_nodes = [] # Adjacency list representation of tree adj = [[] for i in range (N)] # Function to perform DFS Traversal def dfs(s): global removals # Mark the node as true visited[s] = True nodes = 1 # Traverse adjacency list # of child node for child in adj[s]: # If already visited then # omit the node if (visited[child]): continue # Add number of nodes # in subtree nodes + = dfs(child) if (nodes > K): # Increment the count removals + = 1 removed_nodes.append(s) nodes = 0 # Return the nodes return nodes # Function to add edges in graph def addEdge(a, b): adj[a].append(b) adj[b].append(a) # Function that finds the number # of nodes to be removed such that # every subtree has size at most K def findRemovedNodes(K): # Function Call to find the # number of nodes to remove dfs( 1 ) # Print Removed Nodes print ( "Number of nodes removed: " , removals) print ( "Removed Nodes: " , end = ' ' ) for node in removed_nodes: print (node, end = ' ' ) # Driver Code if __name__ = = "__main__" : # Insert of nodes in graph addEdge( 1 , 2 ) addEdge( 1 , 3 ) addEdge( 2 , 4 ) addEdge( 2 , 5 ) addEdge( 3 , 6 ) # Required subtree size K = 3 # Function Call findRemovedNodes(K) # This code is contributed by rutvik_56 |
C#
// C# program for the above approach using System; using System.Collections.Generic; class GFG{ // Variables used to store data globally static readonly int N = 20; static bool []visited = new bool [N]; static int K; static int removals = 0; static List< int > removed_nodes = new List< int >(); // Adjacency list representation of tree static List<List< int > > adj = new List<List< int >>(); // Function to perform DFS Traversal static int dfs( int s) { // Mark the node as true visited[s] = true ; int nodes = 1; // Traverse adjacency list // of child node foreach ( int child in adj[s]) { // If already visited then // omit the node if (visited[child]) continue ; // Add number of nodes // in subtree nodes += dfs(child); } if (nodes > K) { // Increment the count removals++; removed_nodes.Add(s); nodes = 0; } // Return the nodes return nodes; } // Function to add edges in graph static void addEdge( int a, int b) { adj[a].Add(b); adj[b].Add(a); } // Function that finds the number // of nodes to be removed such that // every subtree has size at most K public static void findRemovedNodes( int K) { // Function Call to find the // number of nodes to remove dfs(1); // Print Removed Nodes Console.WriteLine( "Number of nodes" + " removed: " + removals); Console.Write( "Removed Nodes: " ); foreach ( int node in removed_nodes) Console.Write(node + " " ); } // Driver Code public static void Main(String[] args) { // Creating list for all nodes for ( int i = 0; i < N; i++) adj.Add( new List< int >()); // Insert of nodes in graph addEdge(1, 2); addEdge(1, 3); addEdge(2, 4); addEdge(2, 5); addEdge(3, 6); // Required subtree size K = 3; // Function Call findRemovedNodes(K); } } // This code is contributed by Rohit_ranjan |
Javascript
<script> // JavaScript program for the above approach // Variables used to store data globally let N = 20; let visited = new Array(N); let K; let removals = 0; let removed_nodes = []; // Adjacency list representation of tree let adj = []; // Function to perform DFS Traversal function dfs(s) { // Mark the node as true visited[s] = true ; let nodes = 1; // Traverse adjacency list // of child node for (let child = 0; child < adj[s].length; child++) { // If already visited then // omit the node if (visited[adj[s][child]]) continue ; // Add number of nodes // in subtree nodes += dfs(adj[s][child]); } if (nodes > K) { // Increment the count removals++; removed_nodes.push(s); nodes = 0; } // Return the nodes return nodes; } // Function to add edges in graph function addEdge(a, b) { adj[a].push(b); adj[b].push(a); } // Function that finds the number // of nodes to be removed such that // every subtree has size at most K function findRemovedNodes(K) { // Function Call to find the // number of nodes to remove dfs(1); // Print Removed Nodes document.write( "Number of nodes" + " removed: " + removals + "</br>" ); document.write( "Removed Nodes: " ); for (let node = 0; node < removed_nodes.length; node++) document.write(removed_nodes[node] + " " ); } // Creating list for all nodes for (let i = 0; i < N; i++) adj.push([]); // Insert of nodes in graph addEdge(1, 2); addEdge(1, 3); addEdge(2, 4); addEdge(2, 5); addEdge(3, 6); // Required subtree size K = 3; // Function Call findRemovedNodes(K); </script> |
Number of nodes removed: 1 Removed Nodes: 1
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...