Python Program for Detect Cycle in a Directed Graph

A cycle occurs when a path starts and ends at the same vertex, following the direction of the edges. In directed graphs, cycles can cause problems like infinite loops or dependency errors, so detecting them is important in areas like task scheduling and deadlock detection.

We can use Depth-First Search (DFS) with a recursion stack to detect whether a cycle exists in a directed graph or not.

Problem Statement

You are given a directed graph represented using an adjacency list. Your task is to write a Python program to check whether the graph contains a cycle or not.

DFS-Based Cycle Detection

We use Depth-First Search (DFS) traversal and keep track of the nodes in the current recursion path. If we visit a node that is already in the recursion stack, it means a cycle exists.

Steps for DFS Cycle Detection

  • Create a visited list to keep track of visited nodes.
  • Use another list (recursion stack) to track the path of the current DFS.
  • If a node is visited again while it is still in the recursion stack, a cycle is present.
  • If all nodes are checked and no cycle is found, return False.

Graph Visualization

0 1 2 3 Cycle: 1?2?3?1

Python Implementation

Example 1: Graph with Cycle

Here's a complete implementation that detects cycles in a directed graph ?

def is_cyclic_util(v, visited, rec_stack, graph):
    """Helper function for cycle detection using DFS"""
    visited[v] = True
    rec_stack[v] = True

    # Check all neighbors of current vertex
    for neighbor in graph[v]:
        if not visited[neighbor]:
            if is_cyclic_util(neighbor, visited, rec_stack, graph):
                return True
        elif rec_stack[neighbor]:
            return True  # Back edge found - cycle detected

    # Remove vertex from recursion stack before returning
    rec_stack[v] = False
    return False

def has_cycle(graph, num_vertices):
    """Main function to detect cycle in directed graph"""
    visited = [False] * num_vertices
    rec_stack = [False] * num_vertices

    # Check each vertex as starting point
    for vertex in range(num_vertices):
        if not visited[vertex]:
            if is_cyclic_util(vertex, visited, rec_stack, graph):
                return True
    return False

# Create graph with cycle: 0?1?2?3?1
num_vertices = 4
graph = [[] for _ in range(num_vertices)]
graph[0].append(1)  # 0 ? 1
graph[1].append(2)  # 1 ? 2
graph[2].append(3)  # 2 ? 3
graph[3].append(1)  # 3 ? 1 (creates cycle)

result = has_cycle(graph, num_vertices)
print(f"Graph contains cycle: {result}")
Graph contains cycle: True

Example 2: Graph without Cycle

Let's test with a directed acyclic graph (DAG) ?

def is_cyclic_util(v, visited, rec_stack, graph):
    visited[v] = True
    rec_stack[v] = True

    for neighbor in graph[v]:
        if not visited[neighbor]:
            if is_cyclic_util(neighbor, visited, rec_stack, graph):
                return True
        elif rec_stack[neighbor]:
            return True

    rec_stack[v] = False
    return False

def has_cycle(graph, num_vertices):
    visited = [False] * num_vertices
    rec_stack = [False] * num_vertices

    for vertex in range(num_vertices):
        if not visited[vertex]:
            if is_cyclic_util(vertex, visited, rec_stack, graph):
                return True
    return False

# Create acyclic graph: 0?1?2?3
num_vertices = 4
acyclic_graph = [[] for _ in range(num_vertices)]
acyclic_graph[0].append(1)  # 0 ? 1
acyclic_graph[1].append(2)  # 1 ? 2
acyclic_graph[2].append(3)  # 2 ? 3

result = has_cycle(acyclic_graph, num_vertices)
print(f"Acyclic graph contains cycle: {result}")
Acyclic graph contains cycle: False

How the Algorithm Works

The algorithm maintains two boolean arrays:

  • visited[]: Tracks whether a vertex has been visited during DFS
  • rec_stack[]: Tracks vertices in the current recursion path

A cycle exists when we encounter a vertex that is both visited and currently in the recursion stack, indicating a back edge.

Time and Space Complexity

Aspect Complexity Explanation
Time O(V + E) Visit each vertex and edge once
Space O(V) Two boolean arrays of size V

Conclusion

DFS with recursion stack efficiently detects cycles in directed graphs. The algorithm uses two boolean arrays to track visited nodes and current path, making it ideal for applications like deadlock detection and topological sorting validation.

Updated on: 2026-03-25T06:51:02+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements