Undirected Graph Cycle
Undirected Graph Cycle is a medium graphs problem solved with the cycle detection pattern.
The best approach, union-find, runs in O(E · α(V)) time and O(V) space.
Below are 2 approaches in Java, from bfs with parent tracking up.
Problem
Given an undirected graph with V vertices and a list of edges, decide whether it contains a cycle.
Examples
Example 1
- Input
V = 4, edges = [[0,1],[1,2],[2,0],[2,3]]- Output
true- Why
- 0 → 1 → 2 → 0.
Example 2
- Input
V = 4, edges = [[0,1],[1,2],[2,3]]- Output
false
Constraints
1 <= V, E <= 10^5; the graph may be disconnected.
Animated walkthrough
A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.
Concepts first, then the problem and every approach, step by step.
Space to play or pause · ← → to jump a step · click or drag the bar to seek
Solutions
Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.
| Approach | Time | Space |
|---|---|---|
| BFS with parent tracking | O(V + E) | O(V) |
| Union-Find | O(E · α(V)) | O(V) |
1BFS with parent tracking
O(V + E)O(V)BFS from every unvisited node, storing each node's parent. A visited neighbour that is not the parent closes a cycle.
- Queue (node, parent).
- For each neighbour: unvisited → enqueue; visited and != parent → cycle.
class Solution {
public boolean isCycle(int V, int[][] edges) {
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i < V; i++) adj.add(new ArrayList<>());
for (int[] e : edges) { adj.get(e[0]).add(e[1]); adj.get(e[1]).add(e[0]); }
boolean[] seen = new boolean[V];
for (int s = 0; s < V; s++) {
if (seen[s]) continue;
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[] { s, -1 });
seen[s] = true;
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int v : adj.get(cur[0])) {
if (!seen[v]) { seen[v] = true; q.add(new int[] { v, cur[0] }); }
else if (v != cur[1]) return true;
}
}
}
return false;
}
}2Union-Find
O(E · α(V))O(V)Process each edge. If its two endpoints are already in the same set, this edge closes a cycle. Otherwise union them.
- parent[i] = i.
- For each edge (u, v): if find(u) == find(v) return true; else union.
class Solution {
private int[] parent;
public boolean isCycle(int V, int[][] edges) {
parent = new int[V];
for (int i = 0; i < V; i++) parent[i] = i;
for (int[] e : edges) {
int a = find(e[0]), b = find(e[1]);
if (a == b) return true;
parent[a] = b;
}
return false;
}
private int find(int x) {
while (parent[x] != x) x = parent[x] = parent[parent[x]];
return x;
}
}Edge cases to test
- Disconnected components (start a search from every unvisited node)
- The edge back to your parent is not a cycle
Hints
Hint 1
In DFS or BFS, reaching a visited node that is not your parent means there is a cycle.
FAQ
What is the best time complexity for Undirected Graph Cycle?
Union-Find runs in O(E · α(V)) time and O(V) extra space.
Which pattern does Undirected Graph Cycle use?
It is a graphs problem that uses the cycle detection pattern. Other problems with the same pattern: Directed Graph Cycle, Is Graph Bipartite?.
Is there a brute force solution for Undirected Graph Cycle?
Yes. BFS with parent tracking takes O(V + E) time and O(V) space. BFS from every unvisited node, storing each node's parent.
Which edge cases should I test for Undirected Graph Cycle?
Disconnected components (start a search from every unvisited node); The edge back to your parent is not a cycle.