Find whether it is possible to finish all tasks or not from given dependencies

01 Jul, 2022
There are a total of n tasks you have to pick, labelled from 0 to n-1. Some tasks may have prerequisites, for example to pick task 0 you have to first pick task 1, which is expressed as a pair: [0, 1]Given the total number of tasks and a list of prerequisite pairs, is it possible for you to finish all tasks?Examples: 
Input: 2, [[1, 0]] Output: true Explanation: There are a total of 2 tasks to pick. To pick task 1 you should have finished task 0. So it is possible.Input: 2, [[1, 0], [0, 1]] Output: false Explanation: There are a total of 2 tasks to pick. To pick task 1 you should have finished task 0, and to pick task 0 you should also have finished task 1. So it is impossible.Input: 3, [[1, 0], [2, 1], [3, 2]] Output: true Explanation: There are a total of 3 tasks to pick. To pick tasks 1 you should have finished task 0, and to pick task 2 you should have finished task 1 and to pick task 3 you should have finished task 2. So it is possible.
Asked In: Google, Twitter, Amazon and many more companies. 
Solution: We can consider this problem as a graph (related to topological sorting) problem. All tasks are nodes of the graph and if task u is a prerequisite of task v, we will add a directed edge from node u to node v. Now, this problem is equivalent to detecting a cycle in the graph represented by prerequisites. If there is a cycle in the graph, then it is not possible to finish all tasks (because in that case there is no any topological order of tasks). Both BFS and DFS can be used to solve it.Since pair is inconvenient for the implementation of graph algorithms, we first transform it to a graph. If task u is a prerequisite of task v, we will add a directed edge from node u to node v.Prerequisite : Detect Cycle in a Directed GraphUsing DFS For DFS, it will first visit a node, then one neighbor of it, then one neighbor of this neighbor... and so on. If it meets a node which was visited in the current process of DFS visit, a cycle is detected and we will return false. Otherwise it will start from another unvisited node and repeat this process till all the nodes have been visited. Note that you should make two records: one is to record all the visited nodes and the other is to record the visited nodes in the current DFS visit.The code is as follows. We use a vector visited to record all the visited nodes and another vector onpath to record the visited nodes of the current DFS visit. Once the current visit is finished, we reset the onpath value of the starting node to false. 
CPP
Java
Python3
C#
// CPP program to check whether we can finish all// tasks or not from given dependencies.#include <bits/stdc++.h>using namespace std; // Returns adjacency list representation from a list// of pairs.vector<unordered_set<int> > make_graph(int numTasks,            vector<pair<int, int> >& prerequisites){    vector<unordered_set<int> > graph(numTasks);    for (auto pre : prerequisites)        graph[pre.second].insert(pre.first);    return graph;} // A DFS based function to check if there is a cycle// in the directed graph.bool dfs_cycle(vector<unordered_set<int> >& graph, int node,               vector<bool>& onpath, vector<bool>& visited){    if (visited[node])        return false;    onpath[node] = visited[node] = true;    for (int neigh : graph[node])        if (onpath[neigh] || dfs_cycle(graph, neigh, onpath, visited))            return true;    return onpath[node] = false;} // Main function to check whether possible to finish all tasks or notbool canFinish(int numTasks, vector<pair<int, int> >& prerequisites){    vector<unordered_set<int> > graph = make_graph(numTasks, prerequisites);    vector<bool> onpath(numTasks, false), visited(numTasks, false);    for (int i = 0; i < numTasks; i++)        if (!visited[i] && dfs_cycle(graph, i, onpath, visited))            return false;    return true;} int main(){    int numTasks = 4;     vector<pair<int, int> > prerequisites;     // for prerequisites: [[1, 0], [2, 1], [3, 2]]     prerequisites.push_back(make_pair(1, 0));    prerequisites.push_back(make_pair(2, 1));    prerequisites.push_back(make_pair(3, 2));    if (canFinish(numTasks, prerequisites)) {        cout << "Possible to finish all tasks";    }    else {        cout << "Impossible to finish all tasks";    }     return 0;}
// Java program to check whether we can finish all// tasks or not from given dependencies.import java.util.*; public class GFG{         // class to store dependencies as a pair    static class pair{        int first, second;                 pair(int first, int second){            this.first = first;            this.second = second;        }    }         // Returns adjacency list representation from a list    // of pairs.    static ArrayList<ArrayList<Integer>> make_graph(int numTasks,                Vector<pair> prerequisites)    {        ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>(numTasks);         for(int i=0; i<numTasks; i++){            graph.add(new ArrayList<Integer>());        }         for (pair pre : prerequisites)            graph.get(pre.second).add(pre.first);         return graph;    }         // A DFS based function to check if there is a cycle    // in the directed graph.    static boolean dfs_cycle(ArrayList<ArrayList<Integer>> graph, int node,                boolean onpath[], boolean visited[])    {        if (visited[node])            return false;        onpath[node] = visited[node] = true;         for (int neigh : graph.get(node))            if (onpath[neigh] || dfs_cycle(graph, neigh, onpath, visited))                return true;         return onpath[node] = false;    }         // Main function to check whether possible to finish all tasks or not    static boolean canFinish(int numTasks, Vector<pair> prerequisites)    {        ArrayList<ArrayList<Integer>> graph = make_graph(numTasks, prerequisites);                 boolean onpath[] = new boolean[numTasks];        boolean visited[] = new boolean[numTasks];         for (int i = 0; i < numTasks; i++)            if (!visited[i] && dfs_cycle(graph, i, onpath, visited))                return false;         return true;    }         public static void main(String args[])    {        int numTasks = 4;             Vector<pair> prerequisites = new Vector<pair>();;             // for prerequisites: [[1, 0], [2, 1], [3, 2]]             prerequisites.add(new pair(1, 0));        prerequisites.add(new pair(2, 1));        prerequisites.add(new pair(3, 2));                 if (canFinish(numTasks, prerequisites)) {            System.out.println("Possible to finish all tasks");        }        else {            System.out.println("Impossible to finish all tasks");        }    }} // This code is contributed by adityapande88.
# Python3 program to check whether we can finish all# tasks or not from given dependencies. # class to store dependencies as a pairclass pair:    def __init__(self, first, second):        self.first = first        self.second = second # Returns adjacency list representation from a list# of pairs.def make_graph(numTasks, prerequisites):    graph = []    for i in range(numTasks):        graph.append([])     for pre in prerequisites:        graph[pre.second].append(pre.first)     return graph # A DFS based function to check if there is a cycle# in the directed graph.def dfs_cycle(graph, node, onpath, visited):    if visited[node]:        return false    onpath[node] = visited[node] = True    for neigh in graph[node]:        if (onpath[neigh] or dfs_cycle(graph, neigh, onpath, visited)):            return true    return False # Main function to check whether possible to finish all# tasks or notdef canFinish(numTasks, prerequisites):    graph = make_graph(numTasks, prerequisites)    onpath = [False]*numTasks    visited = [False]*numTasks    for i in range(numTasks):        if (not visited[i] and dfs_cycle(graph, i, onpath, visited)):            return False    return True  # Driver code to test above functionsnumTasks = 4prerequisites = [] prerequisites.append(pair(1, 0))prerequisites.append(pair(2, 1))prerequisites.append(pair(3, 2)) if canFinish(numTasks, prerequisites):    print("Possible to finish all tasks")else:    print("Impossible to finish all tasks") # This code is contributed by Abhijeet Kumar(abhijeet19403)
// C# program to check whether we can finish all// tasks or not from given dependencies.using System;using System.Collections.Generic; public class GFG {     // class to store dependencies as a pair    public class pair {        public int first, second;        public pair(int first, int second)        {            this.first = first;            this.second = second;        }    }     // Returns adjacency list representation from a list    // of pairs.    static List<List<int> >    make_graph(int numTasks, List<pair> prerequisites)    {        List<List<int> > graph            = new List<List<int> >(numTasks);         for (int i = 0; i < numTasks; i++) {            graph.Add(new List<int>());        }         foreach(pair pre in prerequisites) graph[pre.second]            .Add(pre.first);         return graph;    }     // A DFS based function to check if there is a cycle    // in the directed graph.    static bool dfs_cycle(List<List<int> > graph, int node,                          bool[] onpath, bool[] visited)    {        if (visited[node])            return false;        onpath[node] = visited[node] = true;         foreach( int neigh in graph[node])          if (onpath[neigh] || dfs_cycle(graph, neigh, onpath,                                     visited))            return true;        //onpath[node] = false;        return false;    }     // Main function to check whether possible to finish all    // tasks or not    static bool canFinish(int numTasks,                          List<pair> prerequisites)    {        List<List<int> > graph            = make_graph(numTasks, prerequisites);         bool[] onpath = new bool[numTasks];        bool[] visited = new bool[numTasks];         for (int i = 0; i < numTasks; i++)            if (!visited[i]                && dfs_cycle(graph, i, onpath, visited))                return false;         return true;    }     public static void Main(String[] args)    {        int numTasks = 4;         List<pair> prerequisites = new List<pair>();        ;         // for prerequisites: [[1, 0], [2, 1], [3, 2]]         prerequisites.Add(new pair(1, 0));        prerequisites.Add(new pair(2, 1));        prerequisites.Add(new pair(3, 2));         if (canFinish(numTasks, prerequisites)) {            Console.WriteLine(                "Possible to finish all tasks");        }        else {            Console.WriteLine(                "Impossible to finish all tasks");        }    }} // This code is contributed by Abhijeet Kumar(abhijeet19403)
Possible to finish all tasks
Using BFS BFS can be used to solve it using the idea of topological sort. If topological sorting is possible, it means there is no cycle and it is possible to finish all the tasks.BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there must be a cycle in the graph and we return false. Otherwise we have found one. We set its indegree to be -1 to prevent from visiting it again and reduce the indegrees of all its neighbors by 1. This process will be repeated for n (number of nodes) times. If we have not returned false, we will return true. 
CPP
Java
Python3
C#
// A BFS based solution to check if we can finish// all tasks or not. This solution is mainly based// on Kahn's algorithm.#include <bits/stdc++.h>using namespace std; // Returns adjacency list representation from a list// of pairs.vector<unordered_set<int> >make_graph(int numTasks,           vector<pair<int, int> >& prerequisites){    vector<unordered_set<int> > graph(numTasks);    for (auto pre : prerequisites)        graph[pre.second].insert(pre.first);    return graph;} // Finds in-degree of every vertexvector<int>compute_indegree(vector<unordered_set<int> >& graph){    vector<int> degrees(graph.size(), 0);    for (auto neighbors : graph)        for (int neigh : neighbors)            degrees[neigh]++;    return degrees;} // Main function to check whether possible to finish all// tasks or notbool canFinish(int numTasks,               vector<pair<int, int> >& prerequisites){    vector<unordered_set<int> > graph        = make_graph(numTasks, prerequisites);    vector<int> degrees = compute_indegree(graph);    for (int i = 0; i < numTasks; i++) {        int j = 0;        for (; j < numTasks; j++)            if (!degrees[j])                break;        if (j == numTasks)            return false;        degrees[j] = -1;        for (int neigh : graph[j])            degrees[neigh]--;    }    return true;} int main(){    int numTasks = 4;    vector<pair<int, int> > prerequisites;    prerequisites.push_back(make_pair(1, 0));    prerequisites.push_back(make_pair(2, 1));    prerequisites.push_back(make_pair(3, 2));    if (canFinish(numTasks, prerequisites)) {        cout << "Possible to finish all tasks";    }    else {        cout << "Impossible to finish all tasks";    }     return 0;}
// A BFS based solution to check if we can finish// all tasks or not. This solution is mainly based// on Kahn's algorithm.import java.util.*; public class GFG {     // class to store dependencies as a pair    static class pair {        int first, second;         pair(int first, int second)        {            this.first = first;            this.second = second;        }    }     // Returns adjacency list representation from a list    // of pairs.    static ArrayList<ArrayList<Integer> >    make_graph(int numTasks, Vector<pair> prerequisites)    {        ArrayList<ArrayList<Integer> > graph            = new ArrayList<ArrayList<Integer> >(numTasks);         for (int i = 0; i < numTasks; i++) {            graph.add(new ArrayList<Integer>());        }         for (pair pre : prerequisites)            graph.get(pre.second).add(pre.first);         return graph;    }     // Finds in-degree of every vertex    static int[] compute_indegree(        ArrayList<ArrayList<Integer> > graph)    {        int degrees[] = new int[graph.size()];         for (ArrayList<Integer> neighbors : graph)            for (int neigh : neighbors)                degrees[neigh]++;         return degrees;    }     // Main function to check whether possible to finish all    // tasks or not    static boolean canFinish(int numTasks,                             Vector<pair> prerequisites)    {        ArrayList<ArrayList<Integer> > graph            = make_graph(numTasks, prerequisites);        int degrees[] = compute_indegree(graph);         for (int i = 0; i < numTasks; i++) {            int j = 0;            for (; j < numTasks; j++)                if (degrees[j] == 0)                    break;             if (j == numTasks)                return false;             degrees[j] = -1;            for (int neigh : graph.get(j))                degrees[neigh]--;        }         return true;    }     public static void main(String args[])    {        int numTasks = 4;        Vector<pair> prerequisites = new Vector<pair>();         prerequisites.add(new pair(1, 0));        prerequisites.add(new pair(2, 1));        prerequisites.add(new pair(3, 2));         if (canFinish(numTasks, prerequisites)) {            System.out.println(                "Possible to finish all tasks");        }        else {            System.out.println(                "Impossible to finish all tasks");        }    }} // This code is contributed by adityapande88.
# A BFS based solution to check if we can finish# all tasks or not. This solution is mainly based# on Kahn's algorithm. # class to store dependencies as a pair  class pair:    def __init__(self, first, second):        self.first = first        self.second = second # Returns adjacency list representation from a list# of pairs.  def make_graph(numTasks, prerequisites):    graph = []    for i in range(numTasks):        graph.append([])     for pre in prerequisites:        graph[pre.second].append(pre.first)     return graph  # Finds in-degree of every vertexdef compute_indegree(graph):    degrees = [0]*len(graph)     for neighbors in graph:        for neigh in neighbors:            degrees[neigh] += 1     return degrees  # Main function to check whether possible to finish all tasks or notdef canFinish(numTasks, prerequisites):    graph = make_graph(numTasks, prerequisites)    degrees = compute_indegree(graph)     for i in range(numTasks):        j = 0        while(j < numTasks):            if (degrees[j] == 0):                break            j += 1         if (j == numTasks):            return False         degrees[j] = -1        for neigh in graph[j]:            degrees[neigh] -= 1     return True numTasks = 4prerequisites = [] prerequisites.append(pair(1, 0))prerequisites.append(pair(2, 1))prerequisites.append(pair(3, 2)) if (canFinish(numTasks, prerequisites)):    print("Possible to finish all tasks")else:    print("Impossible to finish all tasks") # This code is contributed by Lovely Jain
// A BFS based solution to check if we can finish// all tasks or not. This solution is mainly based// on Kahn's algorithm.using System;using System.Collections.Generic; public class GFG {     // class to store dependencies as a pair    public class pair {        public int first, second;         public pair(int first, int second)        {            this.first = first;            this.second = second;        }    }     // Returns adjacency list representation from a list    // of pairs.    static List<List<int> >    make_graph(int numTasks, List<pair> prerequisites)    {        List<List<int> > graph            = new List<List<int> >(numTasks);         for (int i = 0; i < numTasks; i++) {            graph.Add(new List<int>());        }         foreach(pair pre in prerequisites)            graph[pre.second].Add(pre.first);         return graph;    }     // Finds in-degree of every vertex    static int[] compute_indegree(        List<List<int> > graph)    {        int[] degrees = new int[graph.Count];         foreach(List<int> neighbors in graph)            foreach(int neigh in neighbors)                degrees[neigh]++;         return degrees;    }     // Main function to check whether possible to finish all    // tasks or not    static bool canFinish(int numTasks,                             List<pair> prerequisites)    {        List<List<int> > graph            = make_graph(numTasks, prerequisites);        int[] degrees = compute_indegree(graph);         for (int i = 0; i < numTasks; i++) {            int j = 0;            for (; j < numTasks; j++)                if (degrees[j] == 0)                    break;             if (j == numTasks)                return false;             degrees[j] = -1;            foreach(int neigh in graph[j])                degrees[neigh]--;        }         return true;    }     public static void Main(String[] args)    {        int numTasks = 4;        List<pair> prerequisites = new List<pair>();         prerequisites.Add(new pair(1, 0));        prerequisites.Add(new pair(2, 1));        prerequisites.Add(new pair(3, 2));         if (canFinish(numTasks, prerequisites)) {           Console.WriteLine(                "Possible to finish all tasks");        }        else {            Console.WriteLine(                "Impossible to finish all tasks");        }    }} // This code is contributed by Abhijeet Kumar(abhijeet19403)
Possible to finish all tasks
Reference: https://leetcode.com/problems/course-schedule/ 
Using Union-find 
Another approach which is Union-find method can also be used to solve this problem. Each pair we get can be considered in a parent-child relation.
 As soon as we find a pair of tasks which are supposed to be in a parent-child relation, we check if they already have a common parent and hence it means there is a dependency cycle in the tasks which will never end and hence solving such set of tasks is not possible.
C++14
Java
Python3
C#
/* * A union-find based solution for stating whether * the given set of tasks with respective prerequisites * can be finished completely or not. */#include <bits/stdc++.h>using namespace std;class Solution {    // returns true/false stating whether tasks can be    // finished or not    vector<int> arr; public:    Solution(int n)    {        arr.resize(n);        // Initially, everyone is their own child        for (int i = 0; i < n; i++)            arr[i] = i;    }    void makeParent(int a, int b)    {        // find parent of b and make it a's parent        arr[a] = findParent(b);    }     int findParent(int c)    {        // when an independent task is found        if (c == arr)            return c;        // recursively find the parent of given task        return findParent(arr);    }    bool isPossible(int N,                    vector<vector<int> > prerequisites)    {        // traverse through pre-requisites array        for (int i = 0; i < prerequisites.size(); i++) {            // check whether given pre-requisite pair            // already have a common pre-requisite(parent)             if (findParent(prerequisites[i][0])                == findParent(prerequisites[i][1])) {                // tasks cannot be completed because there                // was a cyclic condition in the tasks                return false;            }             // make parent-child relation between            // pre-requisite task and the task dependent on            // it            makeParent(prerequisites[i][0],                       prerequisites[i][1]);        }         // if there was no cycle found, tasks can be        // completed        return true;    }}; // Driver code int main(){    vector<vector<int> > prerequisites{ { 1, 0 },                                        { 2, 1 },                                        { 3, 2 } };     Solution ob(4);     if (ob.isPossible(4, prerequisites)) {        cout << "Yes";    }    else {        cout << "No";    }} // Driver Code Ends // This code was contributed by Abhijeet Kumar(abhijeet19403)
/** A union-find based solution for stating whether* the given set of tasks with respective prerequisites* can be finished completely or not.*/import java.io.*;import java.util.*; //Driver codeclass GFG {    public static void main(String args[]) throws IOException    {                         int prerequisites[][] = new int[][]{ {1,0}, {2,1}, {3,2} };                     Solution ob = new Solution();                   if(ob.isPossible(4, prerequisites))            {                System.out.println("Yes");            }            else{                System.out.println("No");            }    }}//Driver Code Ends  //Solution codeclass Solution {  //returns true/false stating whether tasks can be finished or not   public boolean isPossible(int N, int[][] prerequisites)    {        //make object of Union class for N tasks        Union u = new Union(N);             //traverse through pre-requisites array        for(int i = 0; i < prerequisites.length; i++){          //check whether given pre-requisite pair          //already have a common pre-requisite(parent)          if(u.findParent(prerequisites[i][0]) ==            u.findParent(prerequisites[i][1])) {                                 //tasks cannot be completed because there was                //a cyclic condition in the tasks                return false;            }                       //make parent-child relation between pre-requisite task          //and the task dependent on it            u.makeParent(prerequisites[i][0], prerequisites[i][1]);        }                 //if there was no cycle found, tasks can be completed        return true;    }     }class Union {    //to store the parents of respective tasks    int[] arr;       //parameterized constructor for Union class    public Union(int n){               arr = new int[n];        //Initially, everyone is their own child        for(int i = 0; i < n; i++){            arr[i] = i;            }    }         public void makeParent(int a, int b){        //find parent of b and make it a's parent        arr[a] = findParent(b);    }    public int findParent(int c){        //when an independent task is found         if(c == arr)        return c;        //recursively find the parent of given task        return findParent(arr);    }}
# A union-find based solution for stating whether# the given set of tasks with respective prerequisites# can be finished completely or not.class Solution:        arr = []    # parameterized constructor    def __init__(self,n):        # Initially, everyone is their own child        self.arr = [i for i in range(n)]     def makeParent(self,a, b):        # find parent of b and make it a's parent        self.arr[a] = self.findParent(b)     def findParent(self,c):        # when an independent task is found        if (c == self.arr):            return c        # recursively find the parent of given task        return self.findParent(self.arr)     def isPossible(self,N , prerequisites):        # traverse through pre-requisites array        for i in range(len(prerequisites)):            # check whether given pre-requisite pair            # already have a common pre-requisite(parent)            if (self.findParent(prerequisites[i][0]) == self.findParent(prerequisites[i][1])):            # tasks cannot be completed because there            # was a cyclic condition in the tasks                return false            # make parent-child relation between            # pre-requisite task and the task dependent on            # it            self.makeParent(prerequisites[i][0], prerequisites[i][1])        # if there was no cycle found, tasks can be        # completed        return True       # Driver codeprerequisites = [[1, 0], [2, 1], [3, 2]] ob = Solution(4) if ob.isPossible(4,prerequisites ):    print("Yes")else:    print("No") # Driver Code Ends # This code was contributed by Abhijeet Kumar(abhijeet19403)
/** A union-find based solution for stating whether* the given set of tasks with respective prerequisites* can be finished completely or not.*/using System;using System.Collections.Generic; //Solution code public class Solution {  //returns true/false stating whether tasks can be finished or not   public bool isPossible(int N, int[,] prerequisites)    {        //make object of Union class for N tasks        Union u = new Union(N);             //traverse through pre-requisites array        for(int i = 0; i < prerequisites.Length/2; i++){          //check whether given pre-requisite pair          //already have a common pre-requisite(parent)          if(u.findParent(prerequisites[i,0]) ==            u.findParent(prerequisites[i,1])) {                                 //tasks cannot be completed because there was                //a cyclic condition in the tasks                return false;            }                       //make parent-child relation between pre-requisite task          //and the task dependent on it            u.makeParent(prerequisites[i,0], prerequisites[i,1]);        }                 //if there was no cycle found, tasks can be completed        return true;    }     } public class Union {    //to store the parents of respective tasks    int[] arr;       //parameterized constructor for Union class    public Union(int n){               arr = new int[n];        //Initially, everyone is their own child        for(int i = 0; i < n; i++){            arr[i] = i;            }    }         public void makeParent(int a, int b){        //find parent of b and make it a's parent        arr[a] = findParent(b);    }    public int findParent(int c){        //when an independent task is found         if(c == arr)        return c;        //recursively find the parent of given task        return findParent(arr);    }} //Driver code class GFG {    public static void Main(String[] args)    {                         int[,] prerequisites = new int[,]{ {1,0}, {2,1}, {3,2} };                     Solution ob = new Solution();                   if(ob.isPossible(4, prerequisites))            {                Console.WriteLine("Yes");            }            else{                Console.WriteLine("No");            }    }}//Driver Code Ends // This code was contributed by Abhijeet Kumar(abhijeet19403)
Yes
adityapande88
anikaseth98
vishal0171cse19
rkbhola5
jainlovely450
abhijeet19403
BFS
DFS
graph-cycle
Technical Scripter 2018
Topological Sorting
Graph
Technical Scripter
DFS
Graph
BFS
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.