# Print completed tasks at end according to Dependencies

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

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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:

## Python3

 # Python3 implementation of the approach from collections import defaultdict     # This class represents a directed graph  # using adjacency list representation  class Graph:         # Constructor      def __init__(self):             # Default dictionary to store the graph          self.graph = defaultdict(list)          self.visited = [False]*26        # Function to add an edge to the graph      def addEdge(self, u, v):          self.graph[ord(u)-65].append(ord(v)-65)         # A function used by DFS      def DFSUtil(self, v):                     # Mark the current node as visited          # and print it          self.visited[v]= True            # Recur for all the vertices adjacent          # to this vertex          for i in self.graph[v]:              if self.visited[i] == False:                  self.DFSUtil(i)            # Function to perform the DFS traversal      # It uses recursive DFSUtil()      def DFS(self, start, M):                     # Total vertices          V = len(self.graph)                    # Call the recursive helper function          # to print the DFS traversal starting          # from all vertices one by one          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")    # Driver code  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()

Output:

A B C D

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)

My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Article Tags :
Practice Tags :

Be the First to upvote.

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.