Open In App

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

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:

Below are the implementation of the above approach:




#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;
}




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);
    }
}




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)
    




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);
    }
}




// 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)


Article Tags :