Find any simple cycle in an undirected unweighted Graph
Last Updated :
06 Jan, 2023
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++
#include <bits/stdc++.h>
using namespace std;
#define MAXN 1005
vector<vector< int > > adj(MAXN);
vector< bool > vis(MAXN);
int a, b;
void addedge( int a, int b)
{
adj[a].push_back(b);
adj[b].push_back(a);
}
bool detect_cycle( int node, int par)
{
vis[node] = 1;
for ( auto child : adj[node]) {
if (vis[child] == 0) {
if (detect_cycle(child, node))
return true ;
}
else if (child != par) {
a = child;
b = node;
return true ;
}
}
return false ;
}
vector< int > simple_cycle;
void find_simple_cycle( int a, int b)
{
vector< int > par(MAXN, -1);
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)
continue ;
if (vis[child] == 0) {
par[child] = node;
if (child == b) {
ok = false ;
break ;
}
q.push(child);
vis[child] = 1;
}
}
if (ok == false )
break ;
}
simple_cycle.push_back(a);
int x = b;
while (x != a) {
simple_cycle.push_back(x);
x = par[x];
}
}
int main()
{
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 1);
addedge(1, 3);
if (detect_cycle(1, -1) == true ) {
vis = vector< bool >(MAXN, false );
find_simple_cycle(a, b);
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
import java.util.*;
class GFG{
static final int MAXN = 1005 ;
static Vector<Integer> []adj =
new Vector[MAXN];
static boolean []vis =
new boolean [MAXN];
static int a, b;
static void addedge( int a,
int b)
{
adj[a].add(b);
adj[b].add(a);
}
static boolean detect_cycle( int node,
int par)
{
vis[node] = true ;
for ( int child : adj[node])
{
if (vis[child] == false )
{
if (detect_cycle(child,
node))
return true ;
}
else if (child != par)
{
a = child;
b = node;
return true ;
}
}
return false ;
}
static Vector<Integer> simple_cycle =
new Vector<>();
static void find_simple_cycle( int a,
int b)
{
int []par = new int [MAXN];
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)
continue ;
if (vis[child] == false )
{
par[child] = node;
if (child == b)
{
ok = false ;
break ;
}
q.add(child);
vis[child] = true ;
}
}
if (ok == false )
break ;
}
simple_cycle.add(a);
int x = b;
while (x != a)
{
simple_cycle.add(x);
x = par[x];
}
}
public static void main(String[] args)
{
for ( int i = 0 ; i < adj.length; i++)
adj[i] = new Vector<Integer>();
addedge( 1 , 2 );
addedge( 2 , 3 );
addedge( 3 , 4 );
addedge( 4 , 1 );
addedge( 1 , 3 );
if (detect_cycle( 1 , - 1 ) == true )
{
Arrays.fill(vis, false );
find_simple_cycle(a, b);
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" );
}
}
}
|
Python3
MAXN = 1005
adj = [[] for i in range (MAXN)]
vis = [ False for i in range (MAXN)]
aa = 0
bb = 0
def addedge(a, b):
adj[a].append(b);
adj[b].append(a);
def detect_cycle(node, par):
global aa, bb
vis[node] = True ;
for child in adj[node]:
if (vis[child] = = False ):
if (detect_cycle(child, node)):
return True ;
elif (child ! = par):
aa = child;
bb = node;
return True ;
return False ;
simple_cycle = []
def find_simple_cycle(a, b):
par = [ 0 for i in range (MAXN)]
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):
continue ;
if (vis[child] = = False ):
par[child] = node;
if (child = = b):
ok = False ;
break ;
q.append(child);
vis[child] = True ;
if (ok = = False ):
break ;
simple_cycle.append(a);
x = b;
while (x ! = a):
simple_cycle.append(x);
x = par[x];
if __name__ = = '__main__' :
addedge( 1 , 2 );
addedge( 2 , 3 );
addedge( 3 , 4 );
addedge( 4 , 1 );
addedge( 1 , 3 );
if (detect_cycle( 1 , - 1 ) = = True ):
for i in range (MAXN):
vis[i] = False
find_simple_cycle(aa, bb);
print ( "A simple cycle: " , end = '')
for node in simple_cycle:
print (node, end = " => " )
print (aa)
else :
print ( "The Graph doesn't contain a cycle." )
|
C#
using System;
using System.Collections.Generic;
class GFG{
static readonly int MAXN = 1005;
static List< int > []adj = new List< int >[MAXN];
static bool []vis = new bool [MAXN];
static int a, b;
static void addedge( int a, int b)
{
adj[a].Add(b);
adj[b].Add(a);
}
static bool detect_cycle( int node,
int par)
{
vis[node] = true ;
foreach ( int child in adj[node])
{
if (vis[child] == false )
{
if (detect_cycle(child,
node))
return true ;
}
else if (child != par)
{
a = child;
b = node;
return true ;
}
}
return false ;
}
static List< int > simple_cycle = new List< int >();
static void find_simple_cycle( int a,
int b)
{
int []par = new int [MAXN];
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)
continue ;
if (vis[child] == false )
{
par[child] = node;
if (child == b)
{
ok = false ;
break ;
}
q.Enqueue(child);
vis[child] = true ;
}
}
if (ok == false )
break ;
}
simple_cycle.Add(a);
int x = b;
while (x != a)
{
simple_cycle.Add(x);
x = par[x];
}
}
public static void Main(String[] args)
{
for ( int i = 0; i < adj.Length; i++)
adj[i] = new List< int >();
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 1);
addedge(1, 3);
if (detect_cycle(1, -1) == true )
{
for ( int i = 0; i < vis.Length; i++)
vis[i] = false ;
find_simple_cycle(a, b);
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" );
}
}
}
|
Javascript
<script>
var MAXN = 1005;
var adj = Array.from(Array(MAXN), ()=>Array());
var vis = Array(MAXN).fill( false );
var a, b;
function addedge(a, b)
{
adj[a].push(b);
adj[b].push(a);
}
function detect_cycle(node, par)
{
vis[node] = true ;
for ( var child of adj[node])
{
if (vis[child] == false )
{
if (detect_cycle(child,
node))
return true ;
}
else if (child != par)
{
a = child;
b = node;
return true ;
}
}
return false ;
}
var simple_cycle = [];
function find_simple_cycle(a, b)
{
var par = Array(MAXN);
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)
continue ;
if (vis[child] == false )
{
par[child] = node;
if (child == b)
{
ok = false ;
break ;
}
q.push(child);
vis[child] = true ;
}
}
if (ok == false )
break ;
}
simple_cycle.push(a);
var x = b;
while (x != a)
{
simple_cycle.push(x);
x = par[x];
}
}
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 1);
addedge(1, 3);
if (detect_cycle(1, -1) == true )
{
for ( var i = 0; i < vis.length; i++)
vis[i] = false ;
find_simple_cycle(a, b);
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)
Share your thoughts in the comments
Please Login to comment...