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:
#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 |
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 |
0 4
Time Complexity: O(N)
Auxiliary Space: O(N)