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 Kahn'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:
#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;
}
//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
# 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))
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
// 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++ 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 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
# 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# 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 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)

