Open In App

Find any simple cycle in an undirected unweighted Graph

Last Updated : 06 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an un-directed and unweighted connected graph, find a simple cycle in that graph (if it exists).

Simple Cycle:

A simple cycle is a cycle in a Graph with no repeated vertices (except for the beginning and ending vertex).

Basically, if a cycle can’t be broken down to two or more cycles, then it is a simple cycle. 
For better understanding, refer to the following image: 

The graph in the above picture explains how the cycle 1 -> 2 -> 3 -> 4 -> 1 isn’t a simple cycle 
because, it can be broken into 2 simple cycles 1 -> 3 -> 4 -> 1 and 1 -> 2 -> 3 -> 1. 

Examples: 

Input: edges[]  = {(1, 2), (2, 3), (2, 4), (3, 4)}
 

Output: 2 => 3 => 4 => 2
Explanation:
This graph has only one cycle of length 3 which is a simple cycle.

Input: edges[] = {(1, 2), (2, 3), (3, 4), (1, 4), (1, 3)} 

Output: 1 => 3 => 4 => 1

Approach:  The idea is to check that if the graph contains a cycle or not. This can be done by simply using a DFS
Now, if the graph contains a cycle, we can get the end vertices (say a and b) of that cycle from the DFS itself. Now, if we run a BFS from a to b (ignoring the direct edge between a and b), we’ll be able to get the shortest path from a to b, which will give us the path of the shortest cycle containing the points a and b. The path can be easily tracked by using a parent array. This shortest cycle will be a simple cycle

Proof that the shortest cycle will be a simple cycle:

We can prove this using contradiction. Let’s say there exists another simple cycle inside this cycle. This means the inner simple cycle will have a shorter length and, hence it can be said that there’s a shorter path from a to b. But we have found the shortest path from a to b using BFS. Hence, no shorter path exists and the found path is the shortest. So, no inner cycles can exist inside of the cycle we’ve found. 
Hence, this cycle is a simple cycle.

Below is the implementation of the above approach:

C++




// C++ implementation to find the
// simple cycle in the given path
 
#include <bits/stdc++.h>
using namespace std;
#define MAXN 1005
 
// Declaration of the Graph
vector<vector<int> > adj(MAXN);
 
// Declaration of visited array
vector<bool> vis(MAXN);
int a, b;
 
// Function to add edges
// connecting 'a' and 'b'
// to the graph
void addedge(int a, int b)
{
    adj[a].push_back(b);
    adj[b].push_back(a);
}
 
// Function to detect if the
// graph contains a cycle or not
bool detect_cycle(int node, int par)
{
    // Marking the current node visited
    vis[node] = 1;
    // Traversing to the childs
    // of the current node
    // Simple DFS approach
    for (auto child : adj[node]) {
        if (vis[child] == 0) {
            if (detect_cycle(child, node))
                return true;
        }
 
        // Checking for a back-edge
        else if (child != par) {
            // A cycle is detected
            // Marking the end-vertices
            // of the cycle
            a = child;
            b = node;
            return true;
        }
    }
    return false;
}
 
vector<int> simple_cycle;
 
// Function to get the simple cycle from the
// end-vertices of the cycle we found from DFS
void find_simple_cycle(int a, int b)
{
    // Parent array to get the path
    vector<int> par(MAXN, -1);
 
    // Queue for BFS
    queue<int> q;
    q.push(a);
    bool ok = true;
    while (!q.empty()) {
        int node = q.front();
        q.pop();
        vis[node] = 1;
        for (auto child : adj[node]) {
            if (node == a && child == b)
                // Ignoring the direct edge
                // between a and b
                continue;
 
            if (vis[child] == 0) {
                // Updating the parent array
                par[child] = node;
 
                if (child == b) {
                    // If b is reached,
                    // we've found the
                    // shortest path from
                    // a to b already
                    ok = false;
                    break;
                }
                q.push(child);
                vis[child] = 1;
            }
        }
        // If required task is done
        if (ok == false)
            break;
    }
 
    // Cycle starting from a
    simple_cycle.push_back(a);
    int x = b;
 
    // Until we reach a again
    while (x != a) {
        simple_cycle.push_back(x);
        x = par[x];
    }
}
 
// Driver Code
int main()
{
 
    // Creating the graph
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 1);
    addedge(1, 3);
 
    if (detect_cycle(1, -1) == true) {
        // If cycle is present
 
        // Resetting the visited array
        // for simple cycle finding
        vis = vector<bool>(MAXN, false);
        find_simple_cycle(a, b);
 
        // Printing the simple cycle
        cout << "A simple cycle: ";
        for (auto& node : simple_cycle) {
            cout << node << " => ";
        }
        cout << a;
        cout << "\n";
    }
    else {
        cout << "The Graph doesn't "
             << "contain a cycle.\n";
    }
 
    return 0;
}


Java




// Java implementation to
// find the simple cycle
// in the given path
import java.util.*;
class GFG{
 
  static final int MAXN = 1005;
 
// Declaration of the
// Graph
static Vector<Integer> []adj =
              new Vector[MAXN];
 
// Declaration of visited
// array
static boolean []vis =
       new boolean[MAXN];
static int a, b;
 
// Function to add edges
// connecting 'a' and 'b'
// to the graph
static void addedge(int a,
                    int b)
{
  adj[a].add(b);
  adj[b].add(a);
}
 
// Function to detect if the
// graph contains a cycle or not
static boolean detect_cycle(int node,
                            int par)
{
  // Marking the current
  // node visited
  vis[node] = true;
   
  // Traversing to the childs
  // of the current node
  // Simple DFS approach
  for (int child : adj[node])
  {
    if (vis[child] == false)
    {
      if (detect_cycle(child,
                       node))
        return true;
    }
 
    // Checking for a back-edge
    else if (child != par)
    {
      // A cycle is detected
      // Marking the end-vertices
      // of the cycle
      a = child;
      b = node;
      return true;
    }
  }
  return false;
}
 
static Vector<Integer> simple_cycle =
              new Vector<>();
 
// Function to get the simple
// cycle from the end-vertices
//of the cycle we found from DFS
static void find_simple_cycle(int a,
                              int b)
{
  // Parent array to get the path
  int []par = new int[MAXN];
 
  // Queue for BFS
  Queue<Integer> q =
        new LinkedList<>();
  q.add(a);
  boolean ok = true;
   
  while (!q.isEmpty())
  {
    int node = q.peek();
    q.remove();
    vis[node] = true;
     
    for (int child : adj[node])
    {
      if (node == a &&
          child == b)
        // Ignoring the direct edge
        // between a and b
        continue;
 
      if (vis[child] == false)
      {
        // Updating the parent
        // array
        par[child] = node;
 
        if (child == b)
        {
          // If b is reached,
          // we've found the
          // shortest path from
          // a to b already
          ok = false;
          break;
        }
        q.add(child);
        vis[child] = true;
      }
    }
    // If required task
    // is done
    if (ok == false)
      break;
  }
 
  // Cycle starting from a
  simple_cycle.add(a);
  int x = b;
 
  // Until we reach
  // a again
  while (x != a)
  {
    simple_cycle.add(x);
    x = par[x];
  }
}
 
// Driver Code
public static void main(String[] args)
{
  for (int i = 0; i < adj.length; i++)
    adj[i] = new Vector<Integer>();
   
  // Creating the graph
  addedge(1, 2);
  addedge(2, 3);
  addedge(3, 4);
  addedge(4, 1);
  addedge(1, 3);
 
  if (detect_cycle(1, -1) == true)
  {
    // If cycle is present
    // Resetting the visited array
    // for simple cycle finding
    Arrays.fill(vis, false);
    find_simple_cycle(a, b);
 
    // Printing the simple cycle
    System.out.print("A simple cycle: ");
     
    for (int node : simple_cycle)
    {
      System.out.print(node + " => ");
    }
    System.out.print(a);
    System.out.print("\n");
  }
  else
  {
    System.out.print("The Graph doesn't " +
                     "contain a cycle.\n");
  }
}
}
 
// This code is contributed by shikhasingrajput


Python3




# Python3 implementation to find the
# simple cycle in the given path
 
MAXN = 1005
  
# Declaration of the Graph
adj = [[] for i in range(MAXN)]
  
# Declaration of visited array
vis = [False for i in range(MAXN)]
aa = 0
bb = 0
  
# Function to add edges
# connecting 'a' and 'b'
# to the graph
def addedge(a, b):
 
    adj[a].append(b);
    adj[b].append(a);
      
# Function to detect if the
# graph contains a cycle or not
def detect_cycle(node, par):
    global aa, bb
 
    # Marking the current node visited
    vis[node] = True;
 
    # Traversing to the childs
    # of the current node
    # Simple DFS approach
    for child in adj[node]:
         
        if (vis[child] == False):
            if (detect_cycle(child, node)):
                return True;
  
        # Checking for a back-edge
        elif (child != par):
 
            # A cycle is detected
            # Marking the end-vertices
            # of the cycle
            aa = child;
            bb = node;
            return True;
         
    return False;
  
simple_cycle = []
  
# Function to get the simple cycle from the
# end-vertices of the cycle we found from DFS
def find_simple_cycle(a, b):
 
    # Parent array to get the path
    par = [0 for i in range(MAXN)]
  
    # Queue for BFS
    q = []
    q.append(a);
    ok = True;
    while(len(q) != 0):
         
        node = q[0];
        q.pop(0);
        vis[node] = True;
         
        for child in adj[node]:
             
            if (node == a and child == b):
                 
                # Ignoring the direct edge
                # between a and b
                continue;
  
            if (vis[child] == False):
                 
                # Updating the parent array
                par[child] = node;
  
                if (child == b):
                     
                    # If b is reached,
                    # we've found the
                    # shortest path from
                    # a to b already
                    ok = False;
                    break;
             
                q.append(child);
                vis[child] = True;
 
        # If required task is done
        if (ok == False):
            break;
  
    # Cycle starting from a
    simple_cycle.append(a);
    x = b;
  
    # Until we reach a again
    while (x != a):
        simple_cycle.append(x);
        x = par[x];
      
# Driver Code
if __name__=='__main__':
     
    # Creating the graph
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 1);
    addedge(1, 3);
  
    if (detect_cycle(1, -1) == True):
        # If cycle is present
  
        # Resetting the visited array
        # for simple cycle finding
        for i in range(MAXN):
            vis[i] = False
        find_simple_cycle(aa, bb);
 
        # Printing the simple cycle
        print("A simple cycle: ", end = '')
        for node in simple_cycle:
            print(node, end = " => ")
        print(aa)
 
    else:
        print("The Graph doesn't contain a cycle.")
 
        # This code is contributed by rutvik_56


C#




// C# implementation to
// find the simple cycle
// in the given path
using System;
using System.Collections.Generic;
 
class GFG{
   
static readonly int MAXN = 1005;
   
// Declaration of the
// Graph
static List<int> []adj = new List<int>[MAXN];
   
// Declaration of visited
// array
static bool []vis = new bool[MAXN];
   
static int a, b;
 
// Function to add edges
// connecting 'a' and 'b'
// to the graph
static void addedge(int a, int b)
{
  adj[a].Add(b);
  adj[b].Add(a);
}
 
// Function to detect if the
// graph contains a cycle or not
static bool detect_cycle(int node,
                         int par)
{
   
  // Marking the current
  // node visited
  vis[node] = true;
   
  // Traversing to the childs
  // of the current node
  // Simple DFS approach
  foreach(int child in adj[node])
  {
    if (vis[child] == false)
    {
      if (detect_cycle(child,
                       node))
        return true;
    }
 
    // Checking for a back-edge
    else if (child != par)
    {
       
      // A cycle is detected
      // Marking the end-vertices
      // of the cycle
      a = child;
      b = node;
      return true;
    }
  }
  return false;
}
 
static List<int> simple_cycle = new List<int>();
   
// Function to get the simple
// cycle from the end-vertices
//of the cycle we found from DFS
static void find_simple_cycle(int a,
                              int b)
{
   
  // Parent array to get the path
  int []par = new int[MAXN];
 
  // Queue for BFS
  Queue<int> q = new Queue<int>();
   
  q.Enqueue(a);
  bool ok = true;
   
  while (q.Count != 0)
  {
    int node = q.Peek();
    q.Dequeue();
    vis[node] = true;
     
    foreach(int child in adj[node])
    {
      if (node == a &&
          child == b)
         
        // Ignoring the direct edge
        // between a and b
        continue;
 
      if (vis[child] == false)
      {
         
        // Updating the parent
        // array
        par[child] = node;
 
        if (child == b)
        {
           
          // If b is reached,
          // we've found the
          // shortest path from
          // a to b already
          ok = false;
          break;
        }
        q.Enqueue(child);
        vis[child] = true;
      }
    }
     
    // If required task
    // is done
    if (ok == false)
      break;
  }
 
  // Cycle starting from a
  simple_cycle.Add(a);
  int x = b;
 
  // Until we reach
  // a again
  while (x != a)
  {
    simple_cycle.Add(x);
    x = par[x];
  }
}
 
// Driver Code
public static void Main(String[] args)
{
  for(int i = 0; i < adj.Length; i++)
    adj[i] = new List<int>();
   
  // Creating the graph
  addedge(1, 2);
  addedge(2, 3);
  addedge(3, 4);
  addedge(4, 1);
  addedge(1, 3);
 
  if (detect_cycle(1, -1) == true)
  {
     
    // If cycle is present
    // Resetting the visited array
    // for simple cycle finding
    for(int i = 0; i < vis.Length; i++)
        vis[i] = false;
     
    find_simple_cycle(a, b);
 
    // Printing the simple cycle
    Console.Write("A simple cycle: ");
     
    foreach(int node in simple_cycle)
    {
      Console.Write(node + " => ");
    }
    Console.Write(a);
    Console.Write("\n");
  }
  else
  {
    Console.Write("The Graph doesn't " +
                  "contain a cycle.\n");
  }
}
}
 
// This code is contributed by gauravrajput1


Javascript




<script>
 
// Javascript implementation to
// find the simple cycle
// in the given path
 
var MAXN = 1005;
   
// Declaration of the
// Graph
var adj = Array.from(Array(MAXN), ()=>Array());
   
// Declaration of visited
// array
var vis = Array(MAXN).fill(false);
   
var a, b;
 
// Function to add edges
// connecting 'a' and 'b'
// to the graph
function addedge(a, b)
{
  adj[a].push(b);
  adj[b].push(a);
}
 
// Function to detect if the
// graph contains a cycle or not
function detect_cycle(node, par)
{
   
  // Marking the current
  // node visited
  vis[node] = true;
   
  // Traversing to the childs
  // of the current node
  // Simple DFS approach
  for(var child of adj[node])
  {
    if (vis[child] == false)
    {
      if (detect_cycle(child,
                       node))
        return true;
    }
 
    // Checking for a back-edge
    else if (child != par)
    {
       
      // A cycle is detected
      // Marking the end-vertices
      // of the cycle
      a = child;
      b = node;
      return true;
    }
  }
  return false;
}
 
var simple_cycle = [];
   
// Function to get the simple
// cycle from the end-vertices
//of the cycle we found from DFS
function find_simple_cycle(a, b)
{
   
  // Parent array to get the path
  var par = Array(MAXN);
 
  // Queue for BFS
  var q = [];
   
  q.push(a);
  var ok = true;
   
  while (q.length != 0)
  {
    var node = q[0];
    q.shift();
    vis[node] = true;
     
    for(var child of adj[node])
    {
      if (node == a &&
          child == b)
         
        // Ignoring the direct edge
        // between a and b
        continue;
 
      if (vis[child] == false)
      {
         
        // Updating the parent
        // array
        par[child] = node;
 
        if (child == b)
        {
           
          // If b is reached,
          // we've found the
          // shortest path from
          // a to b already
          ok = false;
          break;
        }
        q.push(child);
        vis[child] = true;
      }
    }
     
    // If required task
    // is done
    if (ok == false)
      break;
  }
 
  // Cycle starting from a
  simple_cycle.push(a);
  var x = b;
 
  // Until we reach
  // a again
  while (x != a)
  {
    simple_cycle.push(x);
    x = par[x];
  }
}
 
// Driver Code
 
// Creating the graph
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 1);
addedge(1, 3);
 
if (detect_cycle(1, -1) == true)
{
   
  // If cycle is present
  // Resetting the visited array
  // for simple cycle finding
  for(var i = 0; i < vis.length; i++)
      vis[i] = false;
   
  find_simple_cycle(a, b);
  // Printing the simple cycle
  document.write("A simple cycle: ");
   
  for(var node of simple_cycle)
  {
    document.write(node + " => ");
  }
  document.write(a);
  document.write("<br>");
}
else
{
  document.write("The Graph doesn't " +
                "contain a cycle.<br>");
}
 
 
</script>


Output: 

A simple cycle: 1 => 4 => 3 => 1

 

Time Complexity: O(V), where V is the number of vertices since we are doing just one DFS and BFS sequentially.
Auxiliary Space: O(MAXN) 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads