Skip to content
Related Articles

Related Articles

Find any simple cycle in an undirected unweighted Graph
  • Difficulty Level : Hard
  • Last Updated : 16 Dec, 2020

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 more 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
Output: 
A simple cycle: 1 => 4 => 3 => 1

 

competitive-programming-img

My Personal Notes arrow_drop_up
Recommended Articles
Page :