A graph is cyclic if it contains at least one cycle, which is a closed path that starts and ends at the same vertex.
A graph that contains no cycles is called an acyclic graph. The method for detecting a cycle differs significantly depending on whether the graph is directed or undirected.
What is a cycle?
A cycle is a path of connected vertices and edges that forms a loop. For a simple graph, a cycle has a length of at least 3, as it requires three distinct vertices to form a closed loop. In a cycle, the sequence of vertices is such that the first and last vertex are the same, while all intermediate vertices are distinct.
Detecting cycles in an undirected graph
In an undirected graph, an edge connects two vertices symmetrically. The primary challenge in cycle detection for undirected graphs is to avoid treating the simple path of an edge and its immediate reverse as a cycle. Algorithms typically address this by keeping track of the parent of the current vertex in the traversal.
Using Depth-First Search (DFS)
The DFS algorithm can be adapted for cycle detection in undirected graphs by performing a traversal and keeping track of visited vertices and their parents.
-
Initialize: Maintain a
visitedarray to track visited vertices and aparentvariable for the current traversal. -
Traverse: Iterate through all vertices. If a vertex has not been visited, start a DFS traversal from it.
-
Detect a cycle: During the DFS traversal from a source vertex
u:- Mark
uas visited. - For each adjacent vertex
v:- If
vis not visited, recursively call DFS onv, withuas its parent. If the recursive call finds a cycle, propagatetrueback up the call stack. - If
vhas been visited and is not the parent ofu, a cycle is detected. This occurs when a back edge is found that links to a previously visited vertex, closing a loop.
- If
- Mark
-
Time and Space Complexity: The time complexity is O(V+E)cap O open paren cap V plus cap E close paren
π(π+πΈ)
, as every vertex and edge is processed once. The space complexity is O(V)cap O open paren cap V close paren
π(π)
for the visited array and the recursion stack.
Using Breadth-First Search (BFS)
BFS can also detect cycles in an undirected graph using a similar parent-tracking approach.
-
Initialize: Use a
visitedarray and a queue to manage the traversal, storing a pair of(vertex, parent). -
Traverse: Iterate through all vertices. If a vertex is not visited, start a BFS from it.
-
Detect a cycle: In the BFS traversal from a source vertex
u:- Mark
uas visited and enqueue(u, -1). - While the queue is not empty, dequeue
(current, parent). - For each adjacent vertex
v:- If
vis visited andvis not the parent ofcurrent, a cycle is detected. - If
vis not visited, mark it as visited and enqueue(v, current).
- If
- Mark
-
Time and Space Complexity: Time complexity is O(V+E)cap O open paren cap V plus cap E close paren
π(π+πΈ)
, and space complexity is O(V)cap O open paren cap V close paren
π(π)
.
Using the Union-Find algorithm
The Union-Find (or Disjoint Set) algorithm is particularly efficient for cycle detection in undirected graphs, especially for large graphs or scenarios where edges are added incrementally.
-
Initialize: Create a disjoint set for each vertex, where each vertex is its own parent.
-
Iterate Edges: Process each edge (u,v)open paren u comma v close paren
(π’,π£)
in the graph.
-
Detect a cycle: For each edge:
-
Find the root (or representative) of the set containing uu
π’
and the set containing vv
π£
.
-
If the roots of uu
π’
and vv
π£
are the same, they already belong to the same set, meaning adding this edge would create a cycle.
-
If the roots are different, union the two sets.
-
-
Time and Space Complexity: With optimizations like Union by Rank and Path Compression, the time complexity is nearly constant for each operation, leading to a total time complexity of O(EΞ±(V))cap O open paren cap E alpha open paren cap V close paren close paren
π(πΈπΌ(π))
, where Ξ±alpha
πΌ
is the inverse Ackermann function, which is highly efficient. Space complexity is O(V)cap O open paren cap V close paren
π(π)
.
Detecting cycles in a directed graph
Detecting cycles in directed graphs is different from undirected graphs because multiple paths to the same vertex don't necessarily form a cycle. A cycle is only present if there's a back edge connecting a vertex to one of its ancestors in the DFS tree.
Using DFS with a recursion stack
A DFS-based method for directed graphs uses a "recursion stack" to track the current path.
-
Initialize
visitedandrecursion_stackarrays tofalsefor all vertices. -
Iterate through vertices. If a vertex is unvisited, start a DFS.
-
In the DFS from vertex
u: Markuas visited and add it to therecursion_stack. -
For each adjacent vertex
v:- If
vis unvisited, recursively call DFS. If it returnstrue, a cycle is found. - If
vis in therecursion_stack, a cycle is detected (a back edge).
- If
-
Remove
ufrom therecursion_stackafter visiting all neighbors.The time complexity is O(V+E)cap O open paren cap V plus cap E close parenπ(π+πΈ)
and space complexity is O(V)cap O open paren cap V close paren
π(π)
.
Using Topological Sort (Kahn's algorithm)
Topological sort orders vertices in a Directed Acyclic Graph (DAG) and is impossible for graphs with cycles.
-
Calculate the in-degree for each vertex.
-
Add vertices with an in-degree of 0 to a queue.
-
While the queue is not empty, dequeue a vertex
u. For each adjacent vertexv, decrement its in-degree. Ifv's in-degree becomes 0, enqueue it. -
A cycle exists if the number of vertices in the topological sort is less than the total vertices in the graph, as cycle vertices won't reach an in-degree of zero.Time complexity is O(V+E)cap O open paren cap V plus cap E close paren
π(π+πΈ)
, and space complexity is O(V)cap O open paren cap V close paren
π(π)
.
Why is cycle detection important?
Cycle detection is crucial in computer science for various applications:
- Deadlock Detection: Identifying deadlocks in resource allocation graphs in operating systems.
- Dependency Management: Resolving circular dependencies in systems like build tools or package managers.
- Version Control Systems: Handling merging and branching in revision graphs.
- Blockchain Technology: Ensuring integrity and order in DAG-based blockchains.
- Garbage Collection: Identifying circular references for memory management.
- Network Routing: Preventing infinite loops in network protocols.