Find the ordering of tasks from given dependencies in C++


Suppose we have n different tasks; these tasks are labeled from 0 to n-1. Some tasks may have prerequisites tasks, so as an example if we want to choose task 2 then we have to first finish the task 1, which is represented as a pair − [2, 1] If we have total number of tasks and a list of prerequisite pairs, we have to find the ordering of tasks to finish all tasks. If there are more than one correct order, we can just return one of them. And if it is impossible to finish all given tasks, return an empty array.

So, if the input is like n = 4, and A = [[1, 0], [2, 0], [3, 2], [3, 1],[4,2]], then the output will be [0, 2, 1, 4, 3]

To solve this, we will follow these steps −

  • Define a function dfs(), this will take graph, start, an onpath, an array visited, an array toposort,

  • if visited[start] is marked, then −

    • return false

  • onpath[start] := true, visited[start] := true

  • for each neighbor in graph[start], do

    • if onpath[neighbor] is true or dfs(graph, neighbor, onpath, visited, toposort) is true, then −

      • return true

    • insert start at the end of toposort

  • return onpath[start] := false

  • From the main method, do the following −

  • graph = create graph with n vertices and edges stored in pre array

  • Define an array toposort

  • Define an array onpath of size n and fill with false

  • Define an array visited of size n and fill with false

  • for initialize i := 0, when i < n, update (increase i by 1), do −

    • if visited[i] is false and dfs(graph, i, onpath, visited, toposort) is true, then −

      • return blank array

  • reverse the array toposort

  • return toposort

Example

Let us see the following implementation to get better understanding −

 Live Demo

#include <bits/stdc++.h>
using namespace std;
vector<unordered_set<int> > create_graph(int n, vector<pair<int, int> >& pre) {
   vector<unordered_set<int> > graph(n);
   for (auto pre : pre)
      graph[pre.second].insert(pre.first);
   return graph;
}
bool dfs(vector<unordered_set<int> >& graph, int start,vector<bool>& onpath, vector<bool>& visited, vector<int>& toposort) {
   if (visited[start])
      return false;
   onpath[start] = visited[start] = true;
   for (int neigh : graph[start])
      if (onpath[neigh] || dfs(graph, neigh, onpath, visited, toposort))
         return true;
   toposort.push_back(start);
   return onpath[start] = false;
}
vector<int> get_order(int n, vector<pair<int, int> > &pre){
   vector<unordered_set<int> > graph = create_graph(n, pre);
   vector<int> toposort;
   vector<bool> onpath(n, false), visited(n, false);
   for (int i = 0; i < n; i++)
      if (!visited[i] && dfs(graph, i, onpath, visited, toposort))
         return {};
   reverse(toposort.begin(), toposort.end());
   return toposort;
}
int main() {
   int n = 4;
   vector<pair<int, int> > pre = {{1, 0}, {2, 0}, {3, 2}, {3, 1},{4,0}};
   vector<int> v = get_order(n, pre);
   for (int i = 0; i < v.size(); i++) {
      cout << v[i] << " ";
   }
}

Input

4, {{1, 0}, {2, 0}, {3, 2}, {3, 1},{4,0}}

Output

0 1 4 2 3

Updated on: 27-Aug-2020

312 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements