Given N dependencies of the form X Y, where X & Y represents two different tasks. The dependency X Y denotes dependency of the form Y -> X i.e, if task Y happens then task X will happen in other words task Y has to be completed first to initiate task X. Also given M tasks that will initiate first. The task is to print all the tasks that will get completed at the end in the lexicographical order.
Note that the tasks will be represented by upper case English letters only.
Input: dep[][] = {{A, B}, {C, B}, {D, A}, {D, C}, {B, E}}, tasks[] = {B, C}
Output: A B C D Task A happens after task B and task D can only happen after the completion of tasks A or C. So, the required order is A B C D.
Input: dep[][] = {{Q, P}, {S, Q}, {Q, R}}, tasks[] = {R}
Output: Q R S
Approach: DFS can be used to solve the problem. The dependencies of the form X Y (Y -> X) can be represented as an edge from node Y to node X in the graph. Initiate the DFS from each of the M initial nodes and mark the nodes that are encountered as visited using a boolean array. At last, print the nodes/tasks that are covered using DFS in lexicographical order. The approach works because DFS will cover all the nodes starting from the initial nodes in sequential manner. Consider the diagram below that represents the first example from the above:
The diagram shows the edges covered during DFS from initial tasks B and C as Red in color. The nodes thus visited were A, B, C and D. Below is the implementation of the above approach:
C++
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
class Graph {
int V;
vector< int >* adj;
bool visited[26];
void DFSUtil( int v);
public :
Graph()
{
this ->V = 26;
adj = new vector< int >[26];
}
void addEdge( char v, char w);
void DFS( char start[], int M);
void printTasks();
};
void Graph::addEdge( char v, char w)
{
adj[v - 65].push_back(w - 65);
}
void Graph::DFSUtil( int v)
{
visited[v] = true ;
vector< int >::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i);
}
void Graph::DFS( char start[], int M)
{
for ( int i = 0; i < V; i++)
visited[i] = false ;
for ( int i = 0; i < M; i++)
DFSUtil(start[i] - 65);
}
void Graph::printTasks()
{
for ( int i = 0; i < 26; i++) {
if (visited[i])
cout << char (i + 65) << " " ;
}
cout << endl;
}
int main()
{
Graph g;
g.addEdge( 'B' , 'A' );
g.addEdge( 'B' , 'C' );
g.addEdge( 'A' , 'D' );
g.addEdge( 'C' , 'D' );
g.addEdge( 'E' , 'B' );
char start[] = { 'B' , 'C' };
int n = sizeof (start) / sizeof ( char );
g.DFS(start, n);
g.printTasks();
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class Graph {
int V;
List<Integer>[] adj;
boolean [] visited;
void DFSUtil( int v)
{
visited[v] = true ;
List<Integer> list = adj[v];
for ( int node : list) {
if (!visited[node])
DFSUtil(node);
}
}
Graph()
{
this .V = 26 ;
adj = new ArrayList[ 26 ];
for ( int i = 0 ; i < 26 ; i++)
adj[i] = new ArrayList<Integer>();
}
void addEdge( char v, char w)
{
adj[v - 65 ].add(w - 65 );
}
void DFS( char start[], int M)
{
visited = new boolean [ 26 ];
for ( int i = 0 ; i < 26 ; i++)
visited[i] = false ;
for ( int i = 0 ; i < M; i++)
DFSUtil(start[i] - 65 );
}
void printTasks()
{
for ( int i = 0 ; i < 26 ; i++) {
if (visited[i])
System.out.print(( char )(i + 65 ) + " " );
}
System.out.println();
}
public static void main(String[] args)
{
Graph g = new Graph();
g.addEdge( 'B' , 'A' );
g.addEdge( 'B' , 'C' );
g.addEdge( 'A' , 'D' );
g.addEdge( 'C' , 'D' );
g.addEdge( 'E' , 'B' );
char start[] = { 'B' , 'C' };
int n = start.length;
g.DFS(start, n);
g.printTasks();
}
}
|
Python3
from collections import defaultdict
class Graph:
def __init__( self ):
self .graph = defaultdict( list )
self .visited = [ False ] * 26
def addEdge( self , u, v):
self .graph[ ord (u) - 65 ].append( ord (v) - 65 )
def DFSUtil( self , v):
self .visited[v] = True
for i in self .graph[v]:
if self .visited[i] = = False :
self .DFSUtil(i)
def DFS( self , start, M):
V = len ( self .graph)
for i in range (M):
self .DFSUtil( ord (start[i]) - 65 )
def printOrder( self ):
for i in range ( 26 ):
if self .visited[i] = = True :
print ( chr (i + 65 ), end = " " )
print ( "\n" )
g = Graph()
g.addEdge( 'B' , 'A' )
g.addEdge( 'B' , 'C' )
g.addEdge( 'A' , 'D' )
g.addEdge( 'C' , 'D' )
g.addEdge( 'E' , 'B' )
g.DFS([ 'B' , 'C' ], 2 )
g.printOrder()
|
Javascript
class Graph {
constructor() {
this .V = 26;
this .adj = new Array(26).fill([]);
this .visited = new Array(26).fill( false );
}
addEdge(v, w) {
this .adj[v.charCodeAt(0)-65].push(w.charCodeAt(0) - 65);
}
DFSUtil(v) {
this .visited[v] = true ;
for (let i = 0; i < this .adj[v].length; i++)
if (! this .visited[ this .adj[v][i]])
this .DFSUtil( this .adj[v][i]);
}
DFS(start, M) {
for (let i = 0; i < this .V; i++)
this .visited[i] = false ;
for (let i = 0; i < M; i++)
this .DFSUtil(start[i].charCodeAt(0) - 65);
}
printTasks() {
for (let i = 0; i < 26; i++) {
if ( this .visited[i])
console.log(String.fromCharCode(i + 65) + " " );
}
console.log( "\n" );
}
}
let g = new Graph();
g.addEdge('B ', ' A ');
g.addEdge(' B ', ' C ');
g.addEdge(' A ', ' D ');
g.addEdge(' C ', ' D ');
g.addEdge(' E ', ' B ');
// Initial tasks to be run
let start = [' B ', ' C'];
let n = start.length;
g.DFS(start, n);
g.printTasks();
|
C#
using System;
using System.Collections.Generic;
class Graph
{
private int V = 26;
private List< int >[] adj;
private bool [] visited = new bool [26];
public Graph()
{
adj = new List< int >[26];
for ( int i = 0; i < 26; i++)
{
adj[i] = new List< int >();
}
}
public void AddEdge( char v, char w)
{
adj[v - 65].Add(w - 65);
}
private void DFSUtil( int v)
{
visited[v] = true ;
foreach ( int i in adj[v])
{
if (!visited[i])
{
DFSUtil(i);
}
}
}
public void DFS( char [] start)
{
for ( int i = 0; i < V; i++)
{
visited[i] = false ;
}
foreach ( char c in start)
{
DFSUtil(c - 65);
}
}
public void PrintTasks()
{
for ( int i = 0; i < 26; i++)
{
if (visited[i])
{
Console.Write(( char )(i + 65) + " " );
}
}
Console.WriteLine();
}
}
class Program
{
static void Main( string [] args)
{
Graph g = new Graph();
g.AddEdge( 'B' , 'A' );
g.AddEdge( 'B' , 'C' );
g.AddEdge( 'A' , 'D' );
g.AddEdge( 'C' , 'D' );
g.AddEdge( 'E' , 'B' );
char [] start = { 'B' , 'C' };
g.DFS(start);
g.PrintTasks();
}
}
|
Time Complexity: O(V + E) where V is the number of nodes in the graph and E is the number of edges or dependencies. In this case, since V is always 26, so the time complexity is O(26 + E) or just O(E) in the worst case.
Space Complexity: O(V + E)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
15 Feb, 2023
Like Article
Save Article