Python Program to Find if Undirected Graph contains Cycle using BFS

A cycle in an undirected graph occurs when you can start at a vertex and return to it by following edges without retracing the same edge. We can detect cycles using Breadth-First Search (BFS) by tracking parent nodes during traversal.

How BFS Cycle Detection Works

The algorithm uses a queue to traverse the graph level by level. For each visited vertex, we track its parent. If we encounter a visited vertex that is not the current vertex's parent, we've found a cycle.

Implementation

Helper Functions

First, let's define a function to add edges to our adjacency list representation ?

from collections import deque

def add_edge(adj, u, v):
    adj[u].append(v)
    adj[v].append(u)

BFS Cycle Detection

The main cycle detection function uses BFS with parent tracking ?

from collections import deque

def add_edge(adj, u, v):
    adj[u].append(v)
    adj[v].append(u)

def detect_cycle(adj, start, V, visited):
    parent = [-1] * V
    queue = deque()
    
    visited[start] = True
    queue.append(start)
    
    while queue:
        current = queue.popleft()
        
        for neighbor in adj[current]:
            if not visited[neighbor]:
                visited[neighbor] = True
                queue.append(neighbor)
                parent[neighbor] = current
            elif parent[current] != neighbor:
                return True
    
    return False

def has_cycle_disconnected(adj, V):
    visited = [False] * V
    
    for i in range(V):
        if not visited[i] and detect_cycle(adj, i, V, visited):
            return True
    
    return False

# Example usage
V = 5
adj = [[] for i in range(V)]

# Add edges to create a cycle: 0-1-2-0
add_edge(adj, 0, 1)
add_edge(adj, 1, 2)
add_edge(adj, 2, 0)
add_edge(adj, 2, 3)

print("Graph edges:")
print("0 -- 1")
print("1 -- 2") 
print("2 -- 0")
print("2 -- 3")

if has_cycle_disconnected(adj, V):
    print("\nCycle detected: Yes")
else:
    print("\nCycle detected: No")

The output of the above code is ?

Graph edges:
0 -- 1
1 -- 2
2 -- 0
2 -- 3

Cycle detected: Yes

Algorithm Steps

The BFS cycle detection follows these key steps:

  1. Initialize: Create a parent array and mark all vertices as unvisited
  2. BFS Traversal: Use a queue to visit vertices level by level
  3. Parent Tracking: For each vertex, record its parent in the BFS tree
  4. Cycle Check: If we reach a visited vertex that isn't the current vertex's parent, a cycle exists
  5. Disconnected Components: Repeat for all unvisited vertices to handle disconnected graphs

Example Without Cycle

Let's test with a graph that has no cycles ?

from collections import deque

def add_edge(adj, u, v):
    adj[u].append(v)
    adj[v].append(u)

def detect_cycle(adj, start, V, visited):
    parent = [-1] * V
    queue = deque()
    
    visited[start] = True
    queue.append(start)
    
    while queue:
        current = queue.popleft()
        
        for neighbor in adj[current]:
            if not visited[neighbor]:
                visited[neighbor] = True
                queue.append(neighbor)
                parent[neighbor] = current
            elif parent[current] != neighbor:
                return True
    
    return False

def has_cycle_disconnected(adj, V):
    visited = [False] * V
    
    for i in range(V):
        if not visited[i] and detect_cycle(adj, i, V, visited):
            return True
    
    return False

# Tree structure (no cycles)
V = 4
adj = [[] for i in range(V)]

add_edge(adj, 0, 1)
add_edge(adj, 1, 2)
add_edge(adj, 1, 3)

print("Tree edges:")
print("0 -- 1")
print("1 -- 2")
print("1 -- 3")

if has_cycle_disconnected(adj, V):
    print("\nCycle detected: Yes")
else:
    print("\nCycle detected: No")

The output of the above code is ?

Tree edges:
0 -- 1
1 -- 2
1 -- 3

Cycle detected: No

Time and Space Complexity

Time Complexity: O(V + E) where V is vertices and E is edges
Space Complexity: O(V) for the visited array, parent array, and queue

Conclusion

BFS cycle detection works by tracking parent relationships during graph traversal. If we encounter a visited vertex that isn't our parent, we've found a cycle. This approach efficiently handles both connected and disconnected graphs.

Updated on: 2026-03-25T19:12:53+05:30

522 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements