Detect cycle in an undirected graph

Last Updated : 26 Oct, 2026

Given an adjacency list adj[][] representing an undirected graph, check whether the graph contains a cycle.

A cycle is a path that starts and ends at the same vertex without repeating any other vertex.

Examples:

Input: adj[][]= [[1, 2], [0, 2], [0, 1, 3], [2]]

file

Output: true
Explanation: There is a cycle 0 -> 2 -> 1 -> 0

Input: adj[][] = [[1], [0, 2], [1, 3], [2]]

file

Output: false
Explanation: There is no cycle in the given graph.

Try It Yourself
redirect icon

Depth First Search - O(V+E) Time and O(V) Space

The idea is to use Depth First Search (DFS) where we visit a vertex and then explore its adjacent vertices. If we reach a vertex that has already been visited, it may indicate a cycle.

However, in an undirected graph, when DFS moves from u to v, visiting u again from v does not mean that a cycle exists. To handle this, we keep track of the parent of each vertex. The parent is the vertex from which the current vertex was reached during DFS..

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.

  • Mark the current vertex as visited and check all its adjacent vertices.
  • If an adjacent vertex is not visited, continue DFS from that vertex and set the current vertex as its parent.
  • If an adjacent vertex is already visited and is not the parent of the current vertex, a cycle exists.
  • If all vertices are explored without finding a cycle, the graph does not contain a cycle.
C++
//Driver Code Starts
#include <iostream>
#include<vector>
using namespace std;

//Driver Code Ends

bool dfs(int v, vector<vector<int>> &adj, vector<bool> &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<int>> &adj)
{
    int V= adj.size();
    
    // Mark all the vertices as not visited
    vector<bool> 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<int>> 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 False

# Returns 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;

    // Recur for all adjacent vertices
    for (let neighbor of adj[v]) {

        // If an adjacent vertex is not visited
        if (!visited[neighbor]) {
            if (dfs(neighbor, adj, visited, v))
                return true;
        }
        // If an adjacent vertex is visited and is not the parent
        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 vertices as unvisited
    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
let adj = [[1, 2], [0, 2], [0, 1, 3], [2]];

console.log(isCycle(adj) ? "true" : "false");

Output
true

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.

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++
#include <iostream>
#include<vector>
#include<queue>
using namespace std;

// Function to perform BFS from node 'start' to detect cycle
bool bfs(int start, vector<vector<int>>& adj, vector<bool>& 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<int>>& 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;
}

int main() {
    vector<vector<int>> adj = {{1, 2}, {0, 2}, {0, 1, 3}, {2}};
    isCycle(adj) ? cout << "true" : cout << "false";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class GFG {

    // 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;
    }
    
    // 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.println(isCycle(adj) ? "true" : "false");
    }
}
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 False

# Function 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



if __name__ == "__main__":
    adj = [[1, 2],[0, 2],[0, 1, 3],[2]]
    
    print("true" if isCycle(adj) else "false")
C#
using System;
using System.Collections.Generic;

class GFG
{
    // 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;
    }
    
     // 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 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");
    }
}
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;
}

// Driver code
let adj = [[1, 2],[0, 2],[0, 1, 3],[2]];

console.log(isCycle(adj) ? "true" : "false");

Related Articles:

Comment