Detect cycle in an undirected graph (original) (raw)
Given an adjacency list **adj[][] representing an undirected graph, determine whether the graph contains a cycle/loop or not.
A cycle is a path that starts and ends at the same vertex without repeating any edge.
**Examples:
**Input: adj[][]= [[1, 2], [0, 2], [0, 1, 3], [2]]
**Output: true
**Explanation: There is a cycle 0 → 2 → 1 → 0**Input: adj[][] = [[1], [0, 2], [1, 3], [2]]
**Output: false
**Explanation: There is no cycle in the given graph.
Table of Content
- [Approach 1] Using Depth First Search - O(V+E) Time and O(V) Space
- [Approach 2] Using Breadth First Search - O(V+E) Time and O(V) Space
[Approach 1] Using Depth First Search - O(V+E) Time and O(V) Space
The idea is to use Depth First Search (DFS). When we start a DFS from a node, we visit all its connected neighbors one by one. If during this traversal, we reach a node that has already been visited before, it indicates that there might be a cycle, since we’ve come back to a previously explored vertex.
However, there’s one important catch.
In an undirected graph, every edge is bidirectional. That means, if there’s an edge from u → v, then there’s also an edge from v → u.
So, while performing DFS, from u, we go to v. From v, we again see u as one of its neighbors. Since u is already visited, it might look like a cycle — but it’s not.
To avoid this issue, we keep track of the parent node — the node from which we reached the current node in DFS. When we move from u to v, we mark u as the parent of v. Now, while checking the neighbors of v, If a neighbor is not visited, we continue DFS for that node.If a neighbor is already visited and not equal to the parent, it means there’s another path that leads back to this node — and hence, a cycle exists.
C++ `
//Driver Code Starts #include #include using namespace std;
//Driver Code Ends
bool dfs(int v, vector<vector> &adj, vector &visited, int parent) { // Mark the current node as visited visited[v] = true;
// Recur for all the vertices adjacent to this vertex
for (int i : adj[v])
{
// If an adjacent vertex is not visited,
//then recur for that adjacent
if (!visited[i])
{
if (dfs(i, adj, visited, v))
return true;
}
// If an adjacent vertex is visited and is not
//parent of current vertex,
// then there exists a cycle in the graph.
else if (i != parent)
return true;
}
return false;}
// Returns true if the graph contains a cycle, else false. bool isCycle(vector<vector> &adj) { int V= adj.size(); // Mark all the vertices as not visited vector visited(V, false);
for (int u = 0; u < V; u++)
{
if (!visited[u])
{
if (dfs(u, adj, visited, -1))
return true;
}
}
return false;}
//Driver Code Starts
int main() { vector<vector> adj = {{1, 2}, {0, 2}, {0, 1, 3}, {2}}; isCycle(adj) ? cout << "true" : cout << "false";
return 0;} //Driver Code Ends
Java
//Driver Code Starts import java.util.ArrayList;
public class GFG {
//Driver Code Ends
static boolean dfs(int v, ArrayList<ArrayList<Integer>> adj, boolean[] visited, int parent) {
// Mark the current node as visited
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
for (int neighbor : adj.get(v)) {
// If an adjacent vertex is not visited,
// then recur for that adjacent
if (!visited[neighbor]) {
if (dfs(neighbor, adj, visited, v))
return true;
}
// If an adjacent vertex is visited and is not
// parent of current vertex,
// then there exists a cycle in the graph.
else if (neighbor != parent)
return true;
}
return false;
}
// Returns true if the graph contains a cycle, else false.
static boolean isCycle(ArrayList<ArrayList<Integer>> adj) {
int V = adj.size();
// Mark all the vertices as not visited
boolean[] visited = new boolean[V];
for (int u = 0; u < V; u++) {
if (!visited[u]) {
if (dfs(u, adj, visited, -1))
return true;
}
}
return false;
}//Driver Code Starts
// Function to add an edge to the adjacency list
static void addEdge(ArrayList<ArrayList<Integer>> adj, int u, int v) {
adj.get(u).add(v);
adj.get(v).add(u);
}
public static void main(String[] args) {
int V = 4;
ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
// Add edges
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 2);
addEdge(adj, 2, 3);
System.out.print(isCycle(adj) ? "true" : "false");
}}
//Driver Code Ends
Python
def dfs(v, adj, visited, parent):
# Mark the current node as visited
visited[v] = True
# Recur for all the vertices adjacent to this vertex
for neighbor in adj[v]:
# If an adjacent vertex is not visited,
# then recur for that adjacent
if not visited[neighbor]:
if dfs(neighbor, adj, visited, v):
return True
# If an adjacent vertex is visited and is not
# parent of current vertex,
# then there exists a cycle in the graph.
elif neighbor != parent:
return True
return FalseReturns true if the graph contains a cycle, else false.
def isCycle(adj): V = len(adj) # Mark all the vertices as not visited visited = [False] * V
for u in range(V):
if not visited[u]:
if dfs(u, adj, visited, -1):
return True
return False#Driver Code Starts if name == "main": adj = [[1, 2],[0, 2],[0, 1, 3],[2]]
print("true" if isCycle(adj) else "false")#Driver Code Ends
C#
//Driver Code Starts using System; using System.Collections.Generic;
class GFG { //Driver Code Ends
// Function to add an edge to the adjacency list
static void addEdge(List<List<int>> adj, int u, int v)
{
adj[u].Add(v);
adj[v].Add(u);
}
static bool dfs(int v, List<List<int>> adj, bool[] visited, int parent)
{
// Mark the current node as visited
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
foreach (int neighbor in adj[v])
{
// If an adjacent vertex is not visited,
// then recur for that adjacent
if (!visited[neighbor])
{
if (dfs(neighbor, adj, visited, v))
return true;
}
// If an adjacent vertex is visited and is not
// parent of current vertex,
// then there exists a cycle in the graph.
else if (neighbor != parent)
return true;
}
return false;
}
// Returns true if the graph contains a cycle, else false.
static bool isCycle(List<List<int>> adj)
{
int V = adj.Count;
// Mark all the vertices as not visited
bool[] visited = new bool[V];
for (int u = 0; u < V; u++)
{
if (!visited[u])
{
if (dfs(u, adj, visited, -1))
return true;
}
}
return false;
}//Driver Code Starts
static void Main()
{
int V = 4;
List<List<int>> adj = new List<List<int>>();
for (int i = 0; i < V; i++)
adj.Add(new List<int>());
// Add edges
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 2);
addEdge(adj, 2, 3);
Console.Write(isCycle(adj) ? "true" : "false");
}}
//Driver Code Ends
JavaScript
function dfs(v, adj, visited, parent) { // Mark the current node as visited visited[v] = true;
let V = adj.length;
// Recur for all the vertices adjacent to this vertex
for (let i = 0; i < V; i++) {
if (adj[v][i] !== -1) {
let neighbor = i;
// If an adjacent vertex is not visited,
// then recur for that adjacent
if (!visited[neighbor]) {
if (dfs(neighbor, adj, visited, v))
return true;
}
// If an adjacent vertex is visited and is not
// parent of current vertex,
// then there exists a cycle in the graph.
else if (neighbor !== parent)
return true;
}
}
return false;}
// Returns true if the graph contains a cycle, else false. function isCycle(adj) { let V = adj.length; // Mark all the vertices as not visited let visited = Array(V).fill(false);
for (let u = 0; u < V; u++) {
if (!visited[u]) {
if (dfs(u, adj, visited, -1))
return true;
}
}
return false;}
//Driver Code Starts // Driver code let adj = [[1, 2],[0, 2],[0, 1, 3],[2]];
console.log(isCycle(adj) ? "true" : "false"); //Driver Code Ends
`
[Approach 2] Using Breadth First Search - O(V+E) Time and O(V) Space
The idea is quite similar to DFS-based cycle detection, but here we use Breadth First Search (BFS) instead of recursion. BFS explores the graph level by level, ensuring that each node is visited in the shortest possible way. It also helps avoid deep recursion calls, making it more memory-efficient for large graphs.
In BFS, we also maintain a visited array to mark nodes that have been explored and a parent tracker to remember from which node we reached the current one.
If during traversal we encounter a node that is already visited and is not the parent of the current node, it means we’ve found a cycle in the graph.
C++ `
//Driver Code Starts #include #include #include using namespace std; //Driver Code Ends
// Function to perform BFS from node 'start' to detect cycle bool bfs(int start, vector<vector>& adj, vector& visited) {
// Queue stores {current node, parent node}
queue<pair<int, int>> q;
// Start node has no parent
q.push({start, -1});
visited[start] = true;
while (!q.empty()) {
int node = q.front().first;
int parent = q.front().second;
q.pop();
// Traverse all neighbors of current node
for (int neighbor : adj[node]) {
// If neighbor is not visited, mark it visited and push to queue
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push({neighbor, node});
}
// If neighbor is visited and not parent, a cycle is detected
else if (neighbor != parent) {
return true;
}
}
}
// No cycle found starting from this node
return false; }
// Function to check if the undirected graph contains a cycle bool isCycle(vector<vector>& adj) {
int V= adj.size();
// Keep track of visited vertices
vector<bool> visited(V, false);
// Perform BFS from every unvisited node
for (int i = 0; i < V; i++) {
if (!visited[i]) {
// If BFS finds a cycle
if (bfs(i, adj, visited)) {
return true;
}
}
}
// If no cycle is found in any component
return false;}
//Driver Code Starts int main() { vector<vector> adj = {{1, 2}, {0, 2}, {0, 1, 3}, {2}}; isCycle(adj) ? cout << "true" : cout << "false";
return 0;}
//Driver Code Ends
Java
//Driver Code Starts import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue;
public class GFG { //Driver Code Ends
// Function to perform BFS from node 'start' to detect cycle
static boolean bfs(int start, ArrayList<ArrayList<Integer>> adj, boolean[] visited) {
// Queue stores {current node, parent node}
Queue<int[]> q = new LinkedList<>();
// Start node has no parent
q.add(new int[]{start, -1});
visited[start] = true;
while (!q.isEmpty()) {
int node = q.peek()[0];
int parent = q.peek()[1];
q.poll();
// Traverse all neighbors of current node
for (int neighbor : adj.get(node)) {
// If neighbor is not visited, mark it visited and push to queue
if (!visited[neighbor]) {
visited[neighbor] = true;
q.add(new int[]{neighbor, node});
}
// If neighbor is visited and not parent, a cycle is detected
else if (neighbor != parent) {
return true;
}
}
}
// No cycle found starting from this node
return false;
}
// Function to check if the undirected graph contains a cycle
static boolean isCycle(ArrayList<ArrayList<Integer>> adj) {
int V= adj.size();
// Keep track of visited vertices
boolean[] visited = new boolean[V];
// Perform BFS from every unvisited node
for (int i = 0; i < V; i++) {
if (!visited[i]) {
// If BFS finds a cycle
if (bfs(i, adj, visited)) {
return true;
}
}
}
// If no cycle is found in any component
return false;
}//Driver Code Starts // Function to add an edge to the adjacency list static void addEdge(ArrayList<ArrayList> adj, int u, int v) { adj.get(u).add(v); adj.get(v).add(u); }
public static void main(String[] args) {
int V = 4;
ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
// Add edges
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 2);
addEdge(adj, 2, 3);
System.out.println(isCycle(adj) ? "true" : "false");
}}
//Driver Code Ends
Python
from collections import deque
Function to perform BFS from node 'start' to detect cycle
def bfs(start, adj, visited):
# Queue stores [current node, parent node]
q = deque()
# Start node has no parent
q.append([start, -1])
visited[start] = True
while q:
node = q[0][0]
parent = q[0][1]
q.popleft()
# Traverse all neighbors of current node
for neighbor in adj[node]:
# If neighbor is not visited, mark it visited and push to queue
if not visited[neighbor]:
visited[neighbor] = True
q.append([neighbor, node])
# If neighbor is visited and not parent, a cycle is detected
elif neighbor != parent:
return True
# No cycle found starting from this node
return FalseFunction to check if the undirected graph contains a cycle
def isCycle(adj):
V = len(adj)
# Keep track of visited vertices
visited = [False] * V
# Perform BFS from every unvisited node
for i in range(V):
if not visited[i]:
# If BFS finds a cycle
if bfs(i, adj, visited):
return True
# If no cycle is found in any component
return False#Driver Code Starts
if name == "main": adj = [[1, 2],[0, 2],[0, 1, 3],[2]]
print("true" if isCycle(adj) else "false")#Driver Code Ends
C#
//Driver Code Starts using System; using System.Collections.Generic;
class GFG { //Driver Code Ends
// Function to perform BFS from node 'start' to detect cycle
static bool bfs(int start, List<List<int>> adj, bool[] visited)
{
// Queue stores {current node, parent node}
Queue<int[]> q = new Queue<int[]>();
// Start node has no parent
q.Enqueue(new int[] { start, -1 });
visited[start] = true;
while (q.Count > 0)
{
int node = q.Peek()[0];
int parent = q.Peek()[1];
q.Dequeue();
// Traverse all neighbors of current node
foreach (int neighbor in adj[node])
{
// If neighbor is not visited, mark it visited and push to queue
if (!visited[neighbor])
{
visited[neighbor] = true;
q.Enqueue(new int[] { neighbor, node });
}
// If neighbor is visited and not parent, a cycle is detected
else if (neighbor != parent)
{
return true;
}
}
}
// No cycle found starting from this node
return false;
}
// Function to check if the undirected graph contains a cycle
static bool isCycle(List<List<int>> adj)
{
int V = adj.Count;
// Keep track of visited vertices
bool[] visited = new bool[V];
// Perform BFS from every unvisited node
for (int i = 0; i < V; i++)
{
if (!visited[i])
{
// If BFS finds a cycle
if (bfs(i, adj, visited))
{
return true;
}
}
}
// If no cycle is found in any component
return false;
}//Driver Code Starts // Function to add an edge to the adjacency list static void addEdge(List<List> adj, int u, int v) { adj[u].Add(v); adj[v].Add(u); }
static void Main()
{
int V = 4;
List<List<int>> adj = new List<List<int>>();
for (int i = 0; i < V; i++)
adj.Add(new List<int>());
// Add edges
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 2);
addEdge(adj, 2, 3);
Console.WriteLine(isCycle(adj) ? "true" : "false");
}}
//Driver Code Ends
JavaScript
const Deque = require("denque");
// Function to perform BFS from node 'start' to detect cycle function bfs(start, adj, visited) {
// Queue stores [current node, parent node]
let q = new Deque();
// Start node has no parent
q.push([start, -1]);
visited[start] = true;
while (q.length > 0) {
let [node, parent] = q.shift(); // pop from front
// Traverse all neighbors of current node
for (let neighbor of adj[node]) {
// If neighbor is not visited, mark visited and enqueue
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push([neighbor, node]);
}
// If neighbor is visited and not the parent, cycle found
else if (neighbor !== parent) {
return true;
}
}
}
// No cycle found starting from this node
return false;}
// Function to check if the undirected graph contains a cycle function isCycle(adj) { let V = adj.length; let visited = Array(V).fill(false);
// Perform BFS from every unvisited node
for (let i = 0; i < V; i++) {
if (!visited[i]) {
if (bfs(i, adj, visited)) {
return true;
}
}
}
// No cycle found in any component
return false;}
// Example usage //Driver Code Starts let adj = [[1, 2],[0, 2],[0, 1, 3],[2]];
console.log(isCycle(adj) ? "true" : "false");
//Driver Code Ends
`
**Related Articles:

