Open In App

Print all the cycles in an undirected graph

Last Updated : 11 Jul, 2025
Comments
Improve
Suggest changes
41 Likes
Like
Report

Given an undirected graph, print all the vertices that form cycles in it. 
 

Undirected Graph


Input: In the above diagram, the cycles have been marked with dark green color. The output for the above will be 
Output: 3 5 4 6
5 6 10 9
11 12 13
4 3 5 9 10 6 4

Prerequisite: Detect Cycle in a directed graph using colors 

The idea is to generate all possible paths in a given graph, and detect the paths with cycle among them. To do so, start iterating through each edges, and for each node initiate cycle search. Each node is used as starting node of DFS. Create an array path[] to store the current path. The first node of the path is the start node, and if start node is part of edge, check for next node. The cycle is detected when the last node is the next node. To ensure the path is unique, rotate the path to start from smallest node, and then generate the inverse cycle. If the generated cycle is new, add it to final list.

Below is the implementation of the above approach: 
 

C++
// C++ program to find all the 
// cycles in an undirected graph
#include <bits/stdc++.h>
using namespace std;

// Function to check if a node is 
// visited in the current path
bool visited(int node, const vector<int> &path) {
    return find(path.begin(), path.end(), node) != path.end();
}

// Function to rotate a cycle such that 
// it starts with the smallest node
vector<int> rotateToSmallest(vector<int> path) {
    auto minIt = min_element(path.begin(), path.end());
    rotate(path.begin(), minIt, path.end());
    return path;
}

// Function to invert the cycle order
vector<int> invert(vector<int> path) {
    reverse(path.begin(), path.end());
    return rotateToSmallest(path);
}

// Function to check if a cycle is new
bool isNew(const vector<int> &path, 
            vector<vector<int>> &cycles) {
    return find(cycles.begin(), 
            cycles.end(), path) == cycles.end();
}

// Function to find new cycles in the graph
void findNewCycles(vector<int> path, 
    vector<vector<int>> &graph, vector<vector<int>> &cycles) {
    int startNode = path[0];
    int nextNode;
    vector<int> sub;

    // Visit each edge and node of each edge
    for (auto &edge : graph) {
        int node1 = edge[0], node2 = edge[1];

        if (startNode == node1 || startNode == node2) {
            nextNode = (node1 == startNode) ? node2 : node1;

            if (!visited(nextNode, path)) {
                // Neighbor node not on path yet
                sub = {nextNode};
                sub.insert(sub.end(), path.begin(), path.end());
                // Explore extended path
                findNewCycles(sub, graph, cycles);
            } 
            else if (path.size() > 2 && nextNode == path.back()) {
                // Cycle found
                vector<int> p = rotateToSmallest(path);
                vector<int> inv = invert(p);

                if (isNew(p, cycles) && isNew(inv, cycles)) {
                    cycles.push_back(p);
                }
            }
        }
    }
}

// Main function to initiate cycle detection
vector<vector<int>> findCycles(vector<vector<int>> &graph) {

    vector<vector<int>> cycles;

    for (auto &edge : graph) {
        for (int node : edge) {
            findNewCycles({node}, graph, cycles);
        }
    }

    return cycles;
}

int main() {
    vector<vector<int>> graph = {{1, 2}, {2, 3}, {3, 5}, {3, 4}, 
    {4, 7}, {7, 8}, {4, 6}, {6, 5}, {5, 9}, {9, 10}, 
    {10, 6}, {10, 11}, {11, 12}, {12, 13}, {11, 13}};
    vector<vector<int>> cycles = findCycles(graph);
    for (auto &cy : cycles) {
        for (size_t i = 0; i < cy.size(); i++) {
            cout << cy[i];
            if (i != cy.size() - 1) cout << " ";
        }
        cout << endl;
    }
    return 0;
}
Java
// Java program to find all the 
// cycles in an undirected graph
import java.util.*;

class GFG {

    // Function to check if a node is 
    // visited in the current path
    static boolean visited(int node, List<Integer> path) {
        return path.contains(node);
    }

    // Function to rotate a cycle such that 
    // it starts with the smallest node
    static List<Integer> rotateToSmallest(List<Integer> path) {
        Collections.rotate(path, -path.indexOf(Collections.min(path)));
        return path;
    }

    // Function to invert the cycle order
    static List<Integer> invert(List<Integer> path) {
        Collections.reverse(path);
        return rotateToSmallest(path);
    }

    // Function to check if a cycle is new
    static boolean isNew(List<Integer> path, List<List<Integer>> cycles) {
        return !cycles.contains(path);
    }

    // Function to find new cycles in the graph
    static void findNewCycles(List<Integer> path, List<int[]> graph, List<List<Integer>> cycles) {
        int startNode = path.get(0);
        int nextNode;
        List<Integer> sub;

        // Visit each edge and node of each edge
        for (int[] edge : graph) {
            int node1 = edge[0], node2 = edge[1];

            if (startNode == node1 || startNode == node2) {
                nextNode = (node1 == startNode) ? node2 : node1;

                if (!visited(nextNode, path)) {
                    // Neighbor node not on path yet
                    sub = new ArrayList<>();
                    sub.add(nextNode);
                    sub.addAll(path);
                    // Explore extended path
                    findNewCycles(sub, graph, cycles);
                } 
                else if (path.size() > 2 && nextNode == path.get(path.size() - 1)) {
                    // Cycle found
                    List<Integer> p = rotateToSmallest(new ArrayList<>(path));
                    List<Integer> inv = invert(new ArrayList<>(p));

                    if (isNew(p, cycles) && isNew(inv, cycles)) {
                        cycles.add(p);
                    }
                }
            }
        }
    }

    // Main function to initiate cycle detection
    static List<List<Integer>> findCycles(List<int[]> graph) {
        List<List<Integer>> cycles = new ArrayList<>();

        for (int[] edge : graph) {
            for (int node : edge) {
                findNewCycles(Collections.singletonList(node), graph, cycles);
            }
        }

        return cycles;
    }

    public static void main(String[] args) {
        List<int[]> graph = Arrays.asList(new int[][]{{1, 2}, {2, 3}, {3, 5}, {3, 4}, {4, 7}, {7, 8}, 
        {4, 6}, {6, 5}, {5, 9}, {9, 10}, {10, 6}, {10, 11}, {11, 12}, {12, 13}, {11, 13}});

        List<List<Integer>> cycles = findCycles(graph);

        for (List<Integer> cy : cycles) {
            for (int i = 0; i < cy.size(); i++) {
                System.out.print(cy.get(i));
                if (i != cy.size() - 1) System.out.print(" ");
            }
            System.out.println();
        }
    }
}
Python
# Python program to find all the 
# cycles in an undirected graph

# Function to check if a node is 
# visited in the current path
def visited(node, path):
    return node in path

# Function to rotate a cycle such that 
# it starts with the smallest node
def rotate_to_smallest(path):
    min_index = path.index(min(path))
    return path[min_index:] + path[:min_index]

# Function to invert the cycle order
def invert(path):
    return rotate_to_smallest(path[::-1])

# Function to check if a cycle is new
def is_new(path, cycles):
    return path not in cycles

# Function to find new cycles in the graph
def find_new_cycles(path, graph, cycles):
    start_node = path[0]
    
    # Visit each edge and node of each edge
    for node1, node2 in graph:
        if start_node in (node1, node2):
            next_node = node2 if node1 == start_node else node1
            
            if not visited(next_node, path):
                # Neighbor node not on path yet
                sub = [next_node] + path
                # Explore extended path
                find_new_cycles(sub, graph, cycles)
            elif len(path) > 2 and next_node == path[-1]:
                # Cycle found
                p = rotate_to_smallest(path)
                inv = invert(p)

                if is_new(p, cycles) and is_new(inv, cycles):
                    cycles.append(p)

# Main function to initiate cycle detection
def find_cycles(graph):
    cycles = []
    
    for edge in graph:
        for node in edge:
            find_new_cycles([node], graph, cycles)
    
    return cycles

graph = [[1, 2], [2, 3], [3, 5], [3, 4], [4, 7], [7, 8], [4, 6], [6, 5], 
         [5, 9], [9, 10], [10, 6], [10, 11], [11, 12], [12, 13], [11, 13]]

cycles = find_cycles(graph)
for cy in cycles:
    print(" ".join(map(str, cy)))
C#
// C# program to find all the 
// cycles in an undirected graph
using System;
using System.Collections.Generic;
using System.Linq;

class GFG {

    // Function to check if a node is 
    // visited in the current path
    static bool Visited(int node, List<int> path) {
        return path.Contains(node);
    }

    // Function to rotate a cycle such that 
    // it starts with the smallest node
    static List<int> RotateToSmallest(List<int> path) {
        if (path.Count == 0) return path; // Prevent out-of-range errors

        int minIndex = path.IndexOf(path.Min());
        return path.Skip(minIndex).Concat(path.Take(minIndex)).ToList();
    }

    // Function to invert the cycle order
    static List<int> Invert(List<int> path) {
        if (path.Count == 0) return path; // Prevent out-of-range errors

        path.Reverse();
        return RotateToSmallest(path);
    }

    // Function to check if a cycle is new
    static bool IsNew(List<int> path, List<List<int>> cycles) {
        return !cycles.Any(c => c.SequenceEqual(path));
    }

    // Function to find new cycles in the graph
    static void FindNewCycles(List<int> path, List<int[]> graph, List<List<int>> cycles) {
        if (path.Count == 0) return; // Prevent empty path processing

        int startNode = path[0];

        foreach (var edge in graph) {
            int node1 = edge[0], node2 = edge[1];

            if (startNode == node1 || startNode == node2) {
                int nextNode = (node1 == startNode) ? node2 : node1;

                if (!Visited(nextNode, path)) {
                    var sub = new List<int> { nextNode };
                    sub.AddRange(path);
                    FindNewCycles(sub, graph, cycles);
                } 
                else if (path.Count > 2 && nextNode == path.Last()) {
                    var p = RotateToSmallest(new List<int>(path));
                    var inv = Invert(new List<int>(p));

                    if (IsNew(p, cycles) && IsNew(inv, cycles)) {
                        cycles.Add(p);
                    }
                }
            }
        }
    }

    // Main function to initiate cycle detection
    static List<List<int>> FindCycles(List<int[]> graph) {
        List<List<int>> cycles = new List<List<int>>();

        foreach (var edge in graph) {
            foreach (var node in edge) {
                FindNewCycles(new List<int> { node }, graph, cycles);
            }
        }

        return cycles;
    }

    static void Main() {
        List<int[]> graph = new List<int[]> {
            new[] {1, 2}, new[] {2, 3}, new[] {3, 5}, new[] {3, 4}, 
            new[] {4, 7}, new[] {7, 8}, new[] {4, 6}, new[] {6, 5}, 
            new[] {5, 9}, new[] {9, 10}, new[] {10, 6}, new[] {10, 11}, 
            new[] {11, 12}, new[] {12, 13}, new[] {11, 13} 
        };

        List<List<int>> cycles = FindCycles(graph);

        foreach (var cycle in cycles) {
            Console.WriteLine(string.Join(" ", cycle));
        }
    }
}
JavaScript
// JavaScript program to find all the 
// cycles in an undirected graph

// Function to check if a node is 
// visited in the current path
function visited(node, path) {
    return path.includes(node);
}

// Function to rotate a cycle such that 
// it starts with the smallest node
function rotateToSmallest(path) {
    let minIndex = path.indexOf(Math.min(...path));
    return [...path.slice(minIndex), ...path.slice(0, minIndex)];
}

// Function to invert the cycle order
function invert(path) {
    return rotateToSmallest([...path].reverse());
}

// Function to check if a cycle is new
function isNew(path, cycles) {
    return !cycles.some(cycle => JSON.stringify(cycle) === JSON.stringify(path));
}

// Function to find new cycles in the graph
function findNewCycles(path, graph, cycles) {
    let startNode = path[0];

    // Visit each edge and node of each edge
    for (let edge of graph) {
        let [node1, node2] = edge;

        if (startNode === node1 || startNode === node2) {
            let nextNode = (node1 === startNode) ? node2 : node1;

            if (!visited(nextNode, path)) {
                // Neighbor node not on path yet
                let sub = [nextNode, ...path];
                // Explore extended path
                findNewCycles(sub, graph, cycles);
            } 
            else if (path.length > 2 && nextNode === path[path.length - 1]) {
                // Cycle found
                let p = rotateToSmallest([...path]);
                let inv = invert([...p]);

                if (isNew(p, cycles) && isNew(inv, cycles)) {
                    cycles.push(p);
                }
            }
        }
    }
}

// Main function to initiate cycle detection
function findCycles(graph) {
    let cycles = [];

    for (let edge of graph) {
        for (let node of edge) {
            findNewCycles([node], graph, cycles);
        }
    }

    return cycles;
}

let graph = [[1, 2], [2, 3], [3, 5], [3, 4], [4, 7], [7, 8], 
    [4, 6], [6, 5], [5, 9], [9, 10], [10, 6], [10, 11], 
    [11, 12], [12, 13], [11, 13]];

let cycles = findCycles(graph);

for (let cy of cycles) {
    console.log(cy.join(" "));
}

Output
3 4 6 5
3 4 6 10 9 5
5 9 10 6
11 13 12

Time Complexity: O(e * 2n).
1. visited Function:

  • Time Complexity: O(n)
  • Checks if a node is in the current path using std::find.

2. rotateToSmallest Function:

  • Time Complexity: O(n)
  • Rotates the cycle to start with the smallest node using std::min_element and std::rotate.

3. invert Function:

  • Time Complexity: O(n)
  • Inverts the cycle and rotates it to start with the smallest node.

4. isNew Function:

  • Time Complexity: O(m*n)
  • Checks if a cycle is new by searching through the list of found cycles using std::find.
  • m: Number of cycles found so far.
  • n: Length of the path

5. findNewCycles Function:

  • Time Complexity: O(2^n)
  • Recursively explores all possible paths to find cycles.
  • In the worst case, it explores all 2^n paths (exponential).

6. findCycles Function:

  • Time Complexity: O(E * 2^n)
  • Calls findNewCycles for each edge in the graph.
  • E: Number of edges.
  • Multiplies the exponential complexity by E.

Space Complexity: O(n * 2^n), where n is the number of nodes, and 2 ^ n is the number of paths in the worst case.


Explore