Open In App

Detect cycle in Directed Graph using Topological Sort

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a Directed Graph consisting of N vertices and M edges and a set of Edges[][], the task is to check whether the graph contains a cycle or not using Topological sort.

Topological sort of directed graph is a linear ordering of its vertices such that, for every directed edge U -> V from vertex U to vertex V, U comes before V in the ordering. 
 

Examples: 

Input: N = 4, M = 6, Edges[][] = {{0, 1}, {1, 2}, {2, 0}, {0, 2}, {2, 3}, {3, 3}} 
Output: Yes 
Explanation: 
A cycle 0 -> 2 -> 0 exists in the given graph

Input: N = 4, M = 3, Edges[][] = {{0, 1}, {1, 2}, {2, 3}, {0, 2}} 
Output: No 

Approach: 
In Topological Sort, the idea is to visit the parent node followed by the child node. If the given graph contains a cycle, then there is at least one node which is a parent as well as a child so this will break Topological Order. Therefore, after the topological sort, check for every directed edge whether it follows the order or not.

Below is the implementation of the above approach: 

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// n -> is number of nodes in graph
// m -> is number of edges in graph
int   n, m ;
 
// Stack to store the
// visited vertices in
// the Topological Sort
stack<int> s;
 
// Store Topological Order
vector<int> tsort;
 
// Adjacency list to store edges
vector<int> adj[int(1e5) + 1];
 
// To ensure visited vertex
vector<int> visited(int(1e5) + 1);
 
// Function to perform DFS
void dfs(int u)
{
    // Set the vertex as visited
    visited[u] = 1;
 
    for (auto it : adj[u]) {
 
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
 
    // Push into the stack on
    // complete visit of vertex
    s.push(u);
}
 
// Function to check and return
// if a cycle exists or not
bool check_cycle()
{
    // Stores the position of
    // vertex in topological order
    unordered_map<int, int> pos;
    int index = 0;
 
    // Pop all elements from stack
    while (!s.empty()) {
        pos[s.top()] = index;
 
        // Push element to get
        // Topological Order
        tsort.push_back(s.top());
 
        index += 1;
 
        // Pop from the stack
        s.pop();
    }
 
    for (int i = 0; i < n; i++) {
        for (auto it : adj[i]) {
 
            // If parent vertex
            // does not appear first
            if (pos[i] > pos[it]) {
 
                // Cycle exists
                return true;
            }
        }
    }
 
    // Return false if cycle
    // does not exist
    return false;
}
 
// Function to add edges
// from u -> v
void addEdge(int u, int v)
{
    adj[u].push_back(v);
}
 
// Driver Code
int main()
{
    n = 4, m = 5;
 
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
 
    for (int i = 0; i < n; i++) {
        if (visited[i] == 0) {
            dfs(i);
        }
    }
 
    // If cycle exist
    if (check_cycle())
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}


Java




// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
     
static int t, n, m, a;
 
// Stack to store the
// visited vertices in
// the Topological Sort
static Stack<Integer> s;
 
// Store Topological Order
static ArrayList<Integer> tsort;
 
// Adjacency list to store edges
static ArrayList<ArrayList<Integer>> adj;
 
// To ensure visited vertex
static int[] visited = new int[(int)1e5 + 1];
 
// Function to perform DFS
static void dfs(int u)
{
     
    // Set the vertex as visited
    visited[u] = 1;
 
    for(Integer it : adj.get(u))
    {
         
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
     
    // Push into the stack on
    // complete visit of vertex
    s.push(u);
}
 
// Function to check and return
// if a cycle exists or not
static boolean check_cycle()
{
     
    // Stores the position of
    // vertex in topological order
    Map<Integer, Integer> pos = new HashMap<>();
     
    int ind = 0;
     
    // Pop all elements from stack
    while (!s.isEmpty())
    {
        pos.put(s.peek(), ind);
         
        // Push element to get
        // Topological Order
        tsort.add(s.peek());
 
        ind += 1;
         
        // Pop from the stack
        s.pop();
    }
 
    for(int i = 0; i < n; i++)
    {
        for(Integer it : adj.get(i))
        {
             
            // If parent vertex
            // does not appear first
            if (pos.get(i) > pos.get(it))
            {
                 
                // Cycle exists
                return true;
            }
        }
    }
 
    // Return false if cycle
    // does not exist
    return false;
}
 
// Function to add edges
// from u to v
static void addEdge(int u, int v)
{
    adj.get(u).add(v);
}
 
// Driver code   
public static void main (String[] args)
{
    n = 4; m = 5;
     
    s = new Stack<>();
    adj = new ArrayList<>();
    tsort = new ArrayList<>();
     
    for(int i = 0; i < 4; i++)
        adj.add(new ArrayList<>());
         
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
     
    for(int i = 0; i < n; i++)
    {
        if (visited[i] == 0)
        {
            dfs(i);
        }
    }
     
    // If cycle exist
    if (check_cycle())
       System.out.println("Yes");
    else
       System.out.println("No");
}
}
 
// This code is contributed by offbeat


Python3




# Python3 program to implement
# the above approach
t = 0
n = 0
m = 0
a = 0
  
# Stack to store the
# visited vertices in
# the Topological Sort
s = []
  
# Store Topological Order
tsort = []
  
# Adjacency list to store edges
adj = [[] for i in range(100001)]
  
# To ensure visited vertex
visited = [False for i in range(100001)]
  
# Function to perform DFS
def dfs(u):
 
    # Set the vertex as visited
    visited[u] = 1
     
    for it in adj[u]:
 
        # Visit connected vertices
        if (visited[it] == 0):
            dfs(it)
  
    # Push into the stack on
    # complete visit of vertex
    s.append(u)
 
# Function to check and return
# if a cycle exists or not
def check_cycle():
 
    # Stores the position of
    # vertex in topological order
    pos = dict()
     
    ind = 0
     
    # Pop all elements from stack
    while (len(s) != 0):
        pos[s[-1]] = ind
  
        # Push element to get
        # Topological Order
        tsort.append(s[-1])
  
        ind += 1
  
        # Pop from the stack
        s.pop()
     
    for i in range(n):
        for it in adj[i]:
            first = 0 if i not in pos else pos[i]
            second = 0 if it not in pos else pos[it]
 
            # If parent vertex
            # does not appear first
            if (first > second):
  
                # Cycle exists
                return True
  
    # Return false if cycle
    # does not exist
    return False
 
# Function to add edges
# from u to v
def addEdge(u, v):
     
    adj[u].append(v)
 
# Driver Code
if __name__ == "__main__":
     
    n = 4
    m = 5
  
    # Insert edges
    addEdge(0, 1)
    addEdge(0, 2)
    addEdge(1, 2)
    addEdge(2, 0)
    addEdge(2, 3)
     
    for i in range(n):
        if (visited[i] == False):
            dfs(i)
  
    # If cycle exist
    if (check_cycle()):
        print('Yes')
    else:
        print('No')
         
# This code is contributed by rutvik_56


C#




// C# program to implement
// the above approach
using System;
using System.Collections;
using System.Collections.Generic;
  
class GFG{
 
static int n;
  
// Stack to store the
// visited vertices in
// the Topological Sort
static Stack<int> s;
  
// Store Topological Order
static ArrayList tsort;
  
// Adjacency list to store edges
static ArrayList adj;
  
// To ensure visited vertex
static int[] visited = new int[100001];
  
// Function to perform DFS
static void dfs(int u)
{
     
    // Set the vertex as visited
    visited[u] = 1;
  
    foreach(int it in (ArrayList)adj[u])
    {
         
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    }
      
    // Push into the stack on
    // complete visit of vertex
    s.Push(u);
}
  
// Function to check and return
// if a cycle exists or not
static bool check_cycle()
{
     
    // Stores the position of
    // vertex in topological order
    Dictionary<int,
               int> pos = new Dictionary<int,
                                         int>();
      
    int ind = 0;
      
    // Pop all elements from stack
    while (s.Count != 0)
    {
        pos.Add(s.Peek(), ind);
         
        // Push element to get
        // Topological Order
        tsort.Add(s.Peek());
  
        ind += 1;
          
        // Pop from the stack
        s.Pop();
    }
  
    for(int i = 0; i < n; i++)
    {
        foreach(int it in (ArrayList)adj[i])
        {
             
            // If parent vertex
            // does not appear first
            if (pos[i] > pos[it])
            {
                 
                // Cycle exists
                return true;
            }
        }
    }
  
    // Return false if cycle
    // does not exist
    return false;
}
  
// Function to add edges
// from u to v
static void addEdge(int u, int v)
{
    ((ArrayList)adj[u]).Add(v);
}
  
// Driver code   
public static void Main(string[] args)
{
    n = 4;
      
    s = new Stack<int>();
    adj = new ArrayList();
    tsort = new ArrayList();
      
    for(int i = 0; i < 4; i++)
        adj.Add(new ArrayList());
          
    // Insert edges
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(1, 2);
    addEdge(2, 0);
    addEdge(2, 3);
      
    for(int i = 0; i < n; i++)
    {
        if (visited[i] == 0)
        {
            dfs(i);
        }
    }
      
    // If cycle exist
    if (check_cycle())
       Console.WriteLine("Yes");
    else
       Console.WriteLine("No");
}
}
 
// This code is contributed by pratham76


Javascript




<script>
 
// JavaScript Program to implement
// the above approach
 
var t, n, m, a;
 
// Stack to store the
// visited vertices in
// the Topological Sort
var s = [];
 
// Store Topological Order
var tsort = [];
 
// Adjacency list to store edges
var adj = Array.from(Array(100001), ()=>Array());
 
// To ensure visited vertex
var visited = Array(100001).fill(0);
 
//( Function to perform )DFS
function dfs(u)
{
    // Set the vertex as visited
    visited[u] = 1;
 
    adj[u].forEach(it => {
         
 
        // Visit connected vertices
        if (visited[it] == 0)
            dfs(it);
    });
 
    // Push into the stack on
    // complete visit of vertex
    s.push(u);
}
 
// Function to check and return
// if a cycle exists or not
function check_cycle()
{
    // Stores the position of
    // vertex in topological order
    var pos = new Map();
    var ind = 0;
 
    // Pop all elements from stack
    while (s.length!=0) {
        pos.set(s[s.length-1], ind);
 
        // Push element to get
        // Topological Order
        tsort.push(s[s.length-1]);
 
        ind += 1;
 
        // Pop from the stack
        s.pop();
    }
    var ans = false;
    for (var i = 0; i < n; i++) {
        adj[i].forEach(it => {
             
            // If parent vertex
            // does not appear first
            if ((pos.has(i)?pos.get(i):0) >
            (pos.has(it)?pos.get(it):0))
            {
 
                // Cycle exists
                ans = true;
            }
        });
    };
 
    // Return false if cycle
    // does not exist
    return ans;
}
 
// Function to add edges
// from u to v
function addEdge(u, v)
{
    adj[u].push(v);
}
 
// Driver Code
 
n = 4, m = 5;
 
// Insert edges
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 2);
addEdge(2, 0);
addEdge(2, 3);
for (var i = 0; i < n; i++) {
    if (visited[i] == 0) {
        dfs(i);
    }
}
// If cycle exist
if (check_cycle())
    document.write( "Yes");
else
    document.write( "No");
 
 
</script>


Output: 

Yes

 

Time Complexity: O(N + M) 
Auxiliary Space: O(N)
 



Last Updated : 30 Oct, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads