Open In App

Minimum number of nodes to be selected to light up all the edges of the tree (Select Nodes)

Last Updated : 10 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given N nodes of a tree and a list of edges. Find the minimum number of nodes to be selected to light up all the edges of the tree. An edge lights up when at least one node at the end of the edge is selected.

Example:

Input: N = 6, edges[] = {(1,2), (1,3), (2,4), (3,5), (3,6)}
Output: 2
Explanation: Selecting nodes 2 and 3 lights up all the edges.

Input: N = 3, arr[] = {(1,2), (1,3)}
Output: 1
Explanation: Selecting Node 1 lights up all the edges.

Approach:

The idea is to traverses the tree, considering each node and its adjacent nodes, and calculates the minimum number of vertices required to cover all edges. Maintains two values for each node: one for including the node in the cover (val[i][1]) and another for excluding it from the cover (val[i][0]). By considering the best possible combination of including or excluding nodes, determine the minimum size of the vertex cover, ensuring that every edge has at least one endpoint covered. The result is the minimum number of vertices needed to achieve this, which is returned as the output.

Steps to solve the problem:

  • Create an adjacency list (adj) to represent the graph based on the given edges.
  • Initialize a val array to store the number of vertices in the vertex cover. Each element in val is a 2-element array with initial values {0, 1}.
  • Perform a depth-first search (DFS) traversal on the graph starting from node 1.
    • For each node, update the values in the val array based on its children nodes.
    • val[src][0] represents the number of vertices in the vertex cover if the current node is not included.
    • val[src][1] represents the number of vertices in the vertex cover if the current node is included.
    • Return the minimum number of vertices in the vertex cover from the val array for the root node (node 1).

Below are the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// Function to perform depth-first search traversal.
void dfs(vector<int> adj[], int src, int par,
         vector<int> val[])
{
    // iterating over adjacency list of the current source
    // node.
    for (int v : adj[src])
        // if the adjacent node is not the parent node.
        if (v != par)
            // recursively calling dfs on the adjacent node.
            dfs(adj, v, src, val);
 
    // iterating over adjacency list of the current source
    // node.
    for (int v : adj[src]) {
        // if the adjacent node is not the parent node.
        if (v != par) {
            // updating the values in the val array for the
            // current node.
            val[src][0] += val[v][1];
            val[src][1] += min(val[v][1], val[v][0]);
        }
    }
}
 
// Function to count the vertices in the minimum vertex
// cover.
int countVertex(int N, vector<vector<int> > edges)
{
    // creating an adjacency list to store the graph.
    vector<int> adj[N + 1];
    for (int i = 0; i < N - 1; i++) {
        adj[edges[i][0]].push_back(edges[i][1]);
        adj[edges[i][1]].push_back(edges[i][0]);
    }
 
    // creating a val array to store the number of vertices
    // in the vertex cover.
    vector<int> val[N + 1];
    for (int i = 1; i <= N; i++) {
 
        vector<int> x = { 0, 1 };
 
        // val[i] = {0, 1}, it sets up the initial values
        // for the dynamic programming approach, indicating
        // that initially, each node can either be included
        // in the vertex cover (1) or not included (0).
        // These values will be updated as the program
        // performs its calculations.
        val[i] = x;
    }
 
    // calling the dfs function to perform depth-first
    // search.
    dfs(adj, 1, 1, val);
 
    // returning the minimum number of vertices in the
    // vertex cover.
    return min(val[1][0], val[1][1]);
}
 
int main()
{
    vector<vector<int> > edges = {
        { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 3, 6 }
    };
    int N = 6;
    int result = countVertex(N, edges);
    cout << result << endl;
}


Java




import java.util.ArrayList;
 
public class MinimumVertexCover {
 
    // Function to perform depth-first search traversal.
    static void dfs(ArrayList<Integer>[] adj, int src,
                    int par, ArrayList<int[]> val)
    {
        // iterating over adjacency list of the current
        // source node.
        for (int v : adj[src])
            // if the adjacent node is not the parent node.
            if (v != par)
                // recursively calling dfs on the adjacent
                // node.
                dfs(adj, v, src, val);
 
        // iterating over adjacency list of the current
        // source node.
        for (int v : adj[src]) {
            // if the adjacent node is not the parent node.
            if (v != par) {
                // updating the values in the val array for
                // the current node.
                val.get(src)[0] += val.get(v)[1];
                val.get(src)[1] += Math.min(val.get(v)[1],
                                            val.get(v)[0]);
            }
        }
    }
 
    // Function to count the vertices in the minimum vertex
    // cover.
    static int countVertex(int N, int[][] edges)
    {
        // creating an adjacency list to store the graph.
        ArrayList<Integer>[] adj = new ArrayList[N + 1];
        for (int i = 1; i <= N; i++) {
            adj[i] = new ArrayList<>();
        }
 
        for (int[] edge : edges) {
            adj[edge[0]].add(edge[1]);
            adj[edge[1]].add(edge[0]);
        }
 
        // creating a val array to store the number of
        // vertices in the vertex cover.
        ArrayList<int[]> val = new ArrayList<>();
        for (int i = 0; i <= N; i++) {
            int[] x = { 0, 1 };
 
            // val[i] = {0, 1}, it sets up the initial
            // values for the dynamic programming approach,
            // indicating that initially, each node can
            // either be included in the vertex cover (1) or
            // not included (0). These values will be
            // updated as the program performs its
            // calculations.
            val.add(x);
        }
 
        // calling the dfs function to perform depth-first
        // search.
        dfs(adj, 1, 1, val);
 
        // returning the minimum number of vertices in the
        // vertex cover.
        return Math.min(val.get(1)[0], val.get(1)[1]);
    }
 
    public static void main(String[] args)
    {
        int[][] edges = {
            { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 3, 6 }
        };
        int N = 6;
        int result = countVertex(N, edges);
        System.out.println(result);
    }
}


Python3




from collections import defaultdict
 
# Function to perform depth-first search traversal.
def dfs(adj, src, par, val):
    # Iterating over adjacency list of the current source node.
    for v in adj[src]:
        # If the adjacent node is not the parent node.
        if v != par:
            # Recursively calling dfs on the adjacent node.
            dfs(adj, v, src, val)
 
    # Iterating over adjacency list of the current source node.
    for v in adj[src]:
        # If the adjacent node is not the parent node.
        if v != par:
            # Updating the values in the val array for the current node.
            val[src][0] += val[v][1]
            val[src][1] += min(val[v][1], val[v][0])
 
# Function to count the vertices in the minimum vertex cover.
def count_vertex(N, edges):
    # Creating an adjacency list to store the graph.
    adj = defaultdict(list)
    for edge in edges:
        adj[edge[0]].append(edge[1])
        adj[edge[1]].append(edge[0])
 
    # Creating a val array to store the number of vertices in the vertex cover.
    val = {}
    for i in range(1, N + 1):
        # val[i] = [0, 1], it sets up the initial values for the dynamic programming approach,
        # indicating that initially, each node can either be included in the vertex cover (1)
        # or not included (0). These values will be updated as the program performs its calculations.
        val[i] = [0, 1]
 
    # Calling the dfs function to perform depth-first search.
    dfs(adj, 1, 1, val)
 
    # Returning the minimum number of vertices in the vertex cover.
    return min(val[1][0], val[1][1])
 
if __name__ == "__main__":
    edges = [
        [1, 2], [1, 3], [2, 4], [3, 5], [3, 6]
    ]
    N = 6
    result = count_vertex(N, edges)
    print(result)
    


C#




using System;
using System.Collections.Generic;
 
class Program
{
    // Function to perform depth-first search traversal.
    static void DFS(List<int>[] adj, int src, int par, List<int>[] val)
    {
        // Iterating over the adjacency list of the current source node.
        foreach (int v in adj[src])
        {
            // If the adjacent node is not the parent node.
            if (v != par)
            {
                // Recursively calling DFS on the adjacent node.
                DFS(adj, v, src, val);
            }
        }
 
        // Iterating over the adjacency list of the current source node.
        foreach (int v in adj[src])
        {
            // If the adjacent node is not the parent node.
            if (v != par)
            {
                // Updating the values in the val array for the current node.
                val[src][0] += val[v][1];
                val[src][1] += Math.Min(val[v][1], val[v][0]);
            }
        }
    }
 
    // Function to count the vertices in the minimum vertex cover.
    static int CountVertex(int N, List<int>[] edges)
    {
        // Creating an adjacency list to store the graph.
        List<int>[] adj = new List<int>[N + 1];
        for (int i = 1; i <= N; i++)
        {
            adj[i] = new List<int>();
        }
 
        for (int i = 0; i < N - 1; i++)
        {
            adj[edges[i][0]].Add(edges[i][1]);
            adj[edges[i][1]].Add(edges[i][0]);
        }
 
        // Creating a val array to store the number of vertices in the vertex cover.
        List<int>[] val = new List<int>[N + 1];
        for (int i = 1; i <= N; i++)
        {
            val[i] = new List<int> { 0, 1 };
        }
 
        // Calling the DFS function to perform depth-first search.
        DFS(adj, 1, 1, val);
 
        // Returning the minimum number of vertices in the vertex cover.
        return Math.Min(val[1][0], val[1][1]);
    }
 
    static void Main()
    {
        List<int>[] edges = new List<int>[]
        {
            new List<int> { 1, 2 },
            new List<int> { 1, 3 },
            new List<int> { 2, 4 },
            new List<int> { 3, 5 },
            new List<int> { 3, 6 }
        };
        int N = 6;
        int result = CountVertex(N, edges);
        Console.WriteLine(result);
    }
}


Javascript




// Function to perform depth-first search traversal.
function dfs(adj, src, par, val) {
    // Iterating over the adjacency list of the current source node.
    for (const v of adj[src]) {
        // If the adjacent node is not the parent node.
        if (v !== par) {
            // Recursively calling dfs on the adjacent node.
            dfs(adj, v, src, val);
        }
    }
 
    // Iterating over the adjacency list of the current source node.
    for (const v of adj[src]) {
        // If the adjacent node is not the parent node.
        if (v !== par) {
            // Updating the values in the val array for the current node.
            val[src][0] += val[v][1];
            val[src][1] += Math.min(val[v][1], val[v][0]);
        }
    }
}
 
// Function to count the vertices in the minimum vertex cover.
function countVertex(N, edges) {
    // Creating an adjacency list to store the graph.
    const adj = new Array(N + 1).fill(null).map(() => []);
 
    for (const edge of edges) {
        adj[edge[0]].push(edge[1]);
        adj[edge[1]].push(edge[0]);
    }
 
    // Creating a val array to store the number of vertices in the vertex cover.
    const val = new Array(N + 1).fill(null).map(() => [0, 1]);
 
    // Calling the dfs function to perform depth-first search.
    dfs(adj, 1, 1, val);
 
    // Returning the minimum number of vertices in the vertex cover.
    return Math.min(val[1][0], val[1][1]);
}
 
// Driver code
const edges = [
    [1, 2], [1, 3], [2, 4], [3, 5], [3, 6]
];
const N = 6;
const result = countVertex(N, edges);
console.log(result);


Output

2

Time complexity: O(V + E), where V is the number of vertices (nodes) and E is the number of edges in the graph
Auxiliary Space: O(V + E)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads