Open In App

Smallest set of vertices to visit all nodes of the given Graph

Last Updated : 20 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a directed acyclic graph of N nodes, the task is to find the smallest set of vertices from which the complete graph can be visited.

Examples: 

Input: Graph in the image below

Output: 0 4
Explanation: From vertex 0, the set of nodes that can be visited is {0 ,1}. Similarly, from vertex 4, {4, 3, 2} can be visited. Hence, the complete graph can be visited from the set {0, 4} which is of the minimum possible size.

Input: Graph in the image below

Output: 3 4

Approach 1: The given problem can be solved using topological sorting to get the ordering of vertices such that for every directed edge from U to V, U comes before V. Below are the steps to follow:

  • Sort the given array of vertices in topological order using Khan’s Algorithm.
  • Maintain an array visited which keeps track of the visited vertices.
  • Iterate the sorted array perform the following operations:
    • If the current vertex is not visited, insert it into the required set.
    • Visit all the nodes that are reachable from the inserted node using DFS traversal.

 Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
class Solution {
  public:
  // Function to perform DFS
  void dfs(int node, unordered_set<int>& vis,
           map<int, vector<int> >& graph)
  {
 
    // add node to visited set
    vis.insert(node);
 
    for (int adj : graph[node]) {
      if (vis.count(adj) == 0) {
        dfs(adj, vis, graph);
      }
    }
  }
 
  vector<int> solve(vector<vector<int> >& edges)
  {
    map<int, vector<int> > graph;
 
    // dictionary storing
    // indegrees of node
    map<int, int> indeg;
 
    // array to store topological
    // sorting of the array
    vector<int> topo_sort;
    unordered_set<int> vis;
 
    for (auto edge : edges) {
      int u = edge[0], v = edge[1];
      graph[u].push_back(v);
 
      // count indegree of each node
      indeg[v]++;
    }
 
    queue<int> qu;
 
    for (auto u : graph) {
 
      // add to queue, if indegree
      // of node u is 0
      if (indeg[u.first] == 0) {
        qu.push(u.first);
      }
    }
 
    // Run till queue is not empty
    while (!qu.empty()) {
 
      int node = qu.front();
      qu.pop();
 
      // add node to topo_sort
      topo_sort.push_back(node);
 
      // traverse adj nodes
      for (int adj : graph[node]) {
 
        // decrement count of indegree
        // of each adj node by 1
        indeg[adj]--;
 
        // if count becomes 0, then
        // add adj to qu
        if (indeg[adj] == 0) {
          qu.push(adj);
        }
      }
    }
 
    vis.clear();
    vector<int> ans;
 
    // Take each node from topo_sort
    for (int node : topo_sort) {
 
      // check if node is visited
      if (vis.count(node) == 0) {
 
        vis.insert(node);
        ans.push_back(node);
 
        // Mark all the reachable
        // nodes as visited
        dfs(node, vis, graph);
      }
    }
 
    // finally return ans
    return ans;
  }
};
 
// Driver code
int main()
{
  Solution obj;
  vector<vector<int> > edges
    = { { 0, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 } };
 
  // Function call
  vector<int> ans = obj.solve(edges);
  for (int n : ans) {
    cout << n << " ";
  }
  cout << endl;
 
  return 0;
}


Java




//GFG
// JAVA program of the above approach
import java.util.*;
 
public class Solution {
   
  // Function to perform DFS
    private void dfs(int node, Set<Integer> vis, Map<Integer, List<Integer>> graph) {
        vis.add(node);
        for (int adj : graph.getOrDefault(node, new ArrayList<>())) {
            if (!vis.contains(adj)) {
                dfs(adj, vis, graph);
            }
        }
    }
 
    public List<Integer> solve(int[][] edges) {
        Map<Integer, List<Integer>> graph = new HashMap<>();
        Map<Integer, Integer> indeg = new HashMap<>();
 
        List<Integer> topoSort = new ArrayList<>();
        Set<Integer> vis = new HashSet<>();
 
        for (int[] edge : edges) {
            int u = edge[0];
            int v = edge[1];
            graph.putIfAbsent(u, new ArrayList<>());
            graph.get(u).add(v);
            indeg.put(v, indeg.getOrDefault(v, 0) + 1);
        }
 
        Queue<Integer> qu = new LinkedList<>();
        for (int u : graph.keySet()) {
            if (!indeg.containsKey(u)) {
                qu.offer(u);
            }
        }
 
        while (!qu.isEmpty()) {
            int node = qu.poll();
            topoSort.add(node);
            for (int adj : graph.getOrDefault(node, new ArrayList<>())) {
                indeg.put(adj, indeg.get(adj) - 1);
                if (indeg.get(adj) == 0) {
                    qu.offer(adj);
                }
            }
        }
 
        vis = new HashSet<>();
        List<Integer> ans = new ArrayList<>();
        for (int node : topoSort) {
            if (!vis.contains(node)) {
                vis.add(node);
                ans.add(node);
                dfs(node, vis, graph);
            }
        }
 
        return ans;
    }
 
    public static void main(String[] args) {
        Solution obj = new Solution();
        int[][] edges = {{0, 1}, {2, 1}, {3, 2}, {4, 3}};
        List<Integer> ans = obj.solve(edges);
        System.out.println(ans);
    }
}
// This code is written by Sundaram


Python3




# Python program of the above approach
from collections import defaultdict, deque
 
class Solution:
 
    # Function to perform DFS
    def dfs(self, node, vis, graph):
 
        # add node to visited set
        vis.add(node)
 
        for adj in graph[node]:
            if (adj not in vis):
                self.dfs(adj, vis, graph)
 
    def solve(self, edges):
 
        graph = defaultdict(list)
 
        # dictionary storing
        # indegrees of node
        indeg = defaultdict(int)
 
        # array to store topological
        # sorting of the array
        topo_sort = []
        vis = set()
 
        for (u, v) in edges:
            graph[u].append(v)
 
            # count indegree of each node
            indeg[v] += 1
 
        qu = deque()
 
        for u in graph:
 
            # add to ququ ,if indegree
            # of node u is 0
            if(indeg[u] == 0):
                qu.append(u)
 
        # Run till queue is not empty
        while(qu):
 
            node = qu.popleft()
 
            # add node to topo_sort
            topo_sort.append(node)
 
            # traverse adj nodes
            for adj in graph[node]:
 
                # decrement count of indegree
                # of each adj node by 1
                indeg[adj] -= 1
 
                # if count becomes 0, then
                # add adj to qu
                if (indeg[adj] == 0):
                    qu.append(adj)
 
        vis = set()
        ans = []
 
        # Take each node from topo_sort
        for node in topo_sort:
 
            # check if node is visited
            if (node not in vis):
 
                vis.add(node)
                ans.append(node)
 
                # Mark all the reachable
                # nodes as visited
                self.dfs(node, vis, graph)
 
        # finally return ans
        return (ans)
 
 
obj = Solution()
edges = [[0, 1], [2, 1], [3, 2], [4, 3]]
 
ans = obj.solve(edges)
print(" ".join(str(n) for n in ans))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Solution {
    // Function to perform DFS
    private void dfs(int node, HashSet<int> vis,
                     Dictionary<int, List<int> > graph)
    {
        vis.Add(node);
        foreach(int adj in graph.GetValueOrDefault(
            node, new List<int>()))
        {
            if (!vis.Contains(adj)) {
                dfs(adj, vis, graph);
            }
        }
    }
 
    public List<int> Solve(int[][] edges)
    {
        Dictionary<int, List<int> > graph
            = new Dictionary<int, List<int> >();
        Dictionary<int, int> indeg
            = new Dictionary<int, int>();
 
        List<int> topoSort = new List<int>();
        HashSet<int> vis = new HashSet<int>();
 
        foreach(int[] edge in edges)
        {
            int u = edge[0];
            int v = edge[1];
            if (!graph.ContainsKey(u)) {
                graph.Add(u, new List<int>());
            }
            graph[u].Add(v);
            indeg[v] = indeg.GetValueOrDefault(v, 0) + 1;
        }
 
        Queue<int> qu = new Queue<int>();
        foreach(int u in graph.Keys)
        {
            if (!indeg.ContainsKey(u)) {
                qu.Enqueue(u);
            }
        }
 
        while (qu.Count() != 0) {
            int node = qu.Dequeue();
            topoSort.Add(node);
            foreach(int adj in graph.GetValueOrDefault(
                node, new List<int>()))
            {
                indeg[adj] = indeg[adj] - 1;
                if (indeg[adj] == 0) {
                    qu.Enqueue(adj);
                }
            }
        }
 
        vis = new HashSet<int>();
        List<int> ans = new List<int>();
        foreach(int node in topoSort)
        {
            if (!vis.Contains(node)) {
                vis.Add(node);
                ans.Add(node);
                dfs(node, vis, graph);
            }
        }
 
        return ans;
    }
 
    public static void Main()
    {
        Solution obj = new Solution();
        int[][] edges
            = { new int[] { 0, 1 }, new int[] { 2, 1 },
                new int[] { 3, 2 }, new int[] { 4, 3 } };
        List<int> ans = obj.Solve(edges);
        Console.WriteLine(string.Join(", ", ans));
    }
}
// This code is contrubuted by user_dtewbxkn77n


Javascript




// Function to perform DFS
function dfs(node, vis, graph) {
    vis.add(node);
    for (const adj of graph[node] || []) {
        if (!vis.has(adj)) {
            dfs(adj, vis, graph);
        }
    }
}
 
class Solution {
    solve(edges) {
        const graph = {};
        const indeg = {};
 
 
        const topoSort = [];
        const vis = new Set();
 
        // Build graph and calculate indegree
        for (const [u, v] of edges) {
            if (!graph[u]) {
                graph[u] = [];
            }
            graph[u].push(v);
            indeg[v] = (indeg[v] || 0) + 1;
        }
 
        // Enqueue all nodes with 0 indegree
        const qu = [];
        for (const u of Object.keys(graph)) {
            if (!indeg[u]) {
                qu.push(u);
            }
        }
 
        // Perform topological sort
        while (qu.length) {
            const node = qu.shift();
            topoSort.push(node);
            for (const adj of graph[node] || []) {
                indeg[adj]--;
                if (indeg[adj] === 0) {
                    qu.push(adj);
                }
            }
        }
 
        // Perform DFS on unvisited nodes in topoSort
        vis.clear();
        const ans = [];
        for (const node of topoSort) {
            if (!vis.has(node)) {
                vis.add(node);
                ans.push(node);
                dfs(node, vis, graph);
            }
        }
 
        return ans;
 
    }
}
 
 
// Driver code
const obj = new Solution();
const edges = [
    [0, 1],
    [2, 1],
    [3, 2],
    [4, 3],
];
// Function call
const ans = obj.solve(edges);
console.log(ans.join(" "));
 
 
// This code is contributed by phasing17


Output

0 4

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

Approach 2: The given problem can also be solved using the observation that vertices with in-degree 0 are the vertices that can not be reached from any other vertex. Hence, the idea is to find the indegree of each vertex and insert the vertices with in-degree 0 into the required set, as all the other vertices can be visited eventually. 

Below is the implementation of the above approach: 

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
vector<int> solve(vector<vector<int>>& edges)
{
    map<int, int> graph;
 
    // Dictionary storing
    // indegree of nodes
    map<int, int> indeg;
 
    for(auto dt : edges)
    {
        graph[dt[0]] = dt[1];
         
        // Count indegree of
        // each node
        indeg[dt[1]] += 1;
    }
 
    vector<int> ans;
    for(auto it = graph.begin();
             it != graph.end(); ++it)
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.count(it->first))
            ans.push_back(it->first);
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
int main()
{
    vector<vector<int>> edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    vector<int> ans = solve(edges);
    for(auto dt : ans)
        cout << dt << " ";
 
    return 0;
}
 
// This code is contributed by rakeshsahni


Java




// Java program of the above approach
import java.util.*;
 
class GFG{
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
static Vector<Integer> solve(int[][] edges)
{
    HashMap<Integer,Integer> graph = new HashMap<Integer,Integer>();
 
    // Dictionary storing
    // indegree of nodes
    HashMap<Integer,Integer> indeg = new HashMap<Integer,Integer>();
 
    for(int dt[] : edges)
    {
        graph.put(dt[0], dt[1]);
         
        // Count indegree of
        // each node
        if(indeg.containsKey(dt[1])) {
            indeg.put(dt[1], indeg.get(dt[1])+1);
        }
        else
            indeg.put(dt[1], 1);
    }
 
    Vector<Integer> ans = new Vector<Integer>();
    for (Map.Entry<Integer,Integer> it : graph.entrySet())
    {
         
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.containsKey(it.getKey()))
            ans.add(it.getKey());
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    int[][]edges = { { 0, 1 }, { 2, 1 },
                                  { 3, 2 }, { 4, 3 } };
 
    Vector<Integer> ans = solve(edges);
    for(int dt : ans)
        System.out.print(dt+ " ");
 
}
}
 
// This code is contributed by shikhasingrajput


Python3




# Python program of the above approach
from collections import defaultdict
 
class Solution:
     
    # Function to find smallest set
    # of vertices from which the
    # complete graph can be visited
    def solve(self , edges):
 
        graph = defaultdict(list)
 
        # dictionary storing
        # indegree of nodes
        indeg = defaultdict(int)
 
        for (u,v) in edges:
            graph[u].append(v)
 
            # count indegree of
            # each node
            indeg[v] +=1
 
        ans = []
        for u in graph:
             
            # add to ans, if indegree
            # of node u is 0
            if(indeg[u] == 0):
                ans.append(u)
 
        # Return Ans
        return (ans)
             
 
obj = Solution()
edges = [[0,1] , [2,1] , [3,2] , [4,3] ]
 
ans= obj.solve(edges)
print(" ".join(str(n) for n in ans))


C#




// C# program of the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Function to find smallest set
    // of vertices from which the
    // complete graph can be visited
    static List<int> solve(int[, ] edges)
    {
        Dictionary<int, int> graph
            = new Dictionary<int, int>();
 
        // Dictionary storing
        // indegree of nodes
        Dictionary<int, int> indeg
            = new Dictionary<int, int>();
        for (int k = 0; k < edges.GetLength(0); k++) {
            int keys = edges[k, 0];
            int values = edges[k, 1];
            graph.Add(keys, values);
 
            // Count indegree of
            // each node
            if (indeg.ContainsKey(values)) {
                indeg[values] += 1;
            }
            else
                indeg.Add(values, 1);
        }
 
        List<int> ans = new List<int>();
        foreach(KeyValuePair<int, int> it in graph)
        {
 
            // Add to ans, if indegree
            // of node u is 0
            if (!indeg.ContainsKey(it.Key))
                ans.Add(it.Key);
        }
 
        // Return Ans
        return ans;
    }
    public static int[] GetRow(int[, ] matrix, int row)
    {
        var rowLength = matrix.GetLength(1);
        var rowVector = new int[rowLength];
 
        for (var i = 0; i < rowLength; i++)
            rowVector[i] = matrix[row, i];
 
        return rowVector;
    }
   
    // Driver code
    public static void Main(String[] args)
    {
        int[, ] edges
            = { { 0, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 } };
 
        List<int> ans = solve(edges);
        foreach(int dt in ans) Console.Write(dt + " ");
    }
}
 
// This code is contributed by 29AjayKumar


Javascript




// Javascript program of the above approach
 
// Function to find smallest set
// of vertices from which the
// complete graph can be visited
function solve(edges) {
    let graph = new Map();
 
    // Dictionary storing
    // indegree of nodes
    let indeg = new Map();
 
    for (dt of edges) {
        graph.set(dt[0], dt[1]);
 
        // Count indegree of
        // each node
        if (indeg.has(dt[1])) {
            indeg.set(dt[1], indeg.get(dt[1]) + 1);
        }
        else
            indeg.set(dt[1], 1);
    }
 
    let ans = new Array();
    for (key of graph.keys()) {
 
        // Add to ans, if indegree
        // of node u is 0
        if (!indeg.has(key))
            ans.push(key);
    }
 
    // Return Ans
    return ans;
}
 
// Driver code
let edges = [[0, 1], [2, 1],
[3, 2], [4, 3]];
 
let ans = solve(edges);
for (dt of ans)
    console.log(dt + " ");
 
 
// This code is contributed by Saurabh Jaiswal


Output

0 4

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads