Count of simple cycles in an undirected graph having N vertices
Given an undirected unweighted graph of N vertices in the form of adjacency matrix adj[][], the task is to find the number of simple cycles in it.
Input: adj[][] = { { 0, 1, 1, 1 }, { 1, 0, 1, 0 }, { 1, 1, 0, 1 }, { 1, 0, 1, 0 } }
Output: 2
Explanation: The graph is shown below as:
The given graph consists of two simple cycles as shown
Input: adj[][] = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 1 }, { 0, 1, 1, 0 } }
Output: 1
Approach: The given problem can be solved by using Dynamic Programming with Bitmasking, the dynamic programming state for the Hamiltonian paths is defined as the dp[mask][i] as the number of paths that cover the node-set mask and ends at i and iterate from 0 to N-1 and in each iteration, compute the number of loops containing the current node without the previous node and sum them up, Since there are two directions for a loop divide the result by 2. Follow the steps below to solve the problem:
- Initialize a variable ans as 0 that stores the resultant count of cycles.
- Initialize a 2-D array dp[][] array of dimensions 2N and N and initialize it with 0.
- Iterate over the range [0, 2N – 1) using the variable mask and perform the following tasks:
- Initialize 2 variables nodeSet and firstSetBit as the number of set bits and the first set bit in mask.
- If nodeSet equals 1, then set the value of dp[mask][firstSetBit] as 1.
- Now, For each mask having set bits greater than 1, iterate over the range [firstSetBit + 1, N – 1) using the variable j and if the Bitwise AND of mask & 2j is true, then initialize a variable newNodeSet as mask^2j and iterate over the range [0, N) using the variable k and perform the following tasks:
- Check if there is an edge between nodes k and j(k is not equal to j).
- If there is an edge then add the number of loops in this mask that ends at k and does not contain j to the state for the node-set mask as follows dp[mask][j] = dp[mask][j]+ dp[mask XOR 2j][k].
- If adj[j][firstSetBit] is 1 and nodeSet is greater than 2, then add the value of dp[mask][j] to the variable ans.
- After performing the above steps, print the value of ans as the answer.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
void findNumberOfSimpleCycles(
int N, vector<vector< int > > adj)
{
int ans = 0;
int dp[(1 << N)][N];
memset (dp, 0, sizeof dp);
for ( int mask = 0;
mask < (1 << N); mask++) {
int nodeSet
= __builtin_popcountll(mask);
int firstSetBit
= __builtin_ffsl(mask);
if (nodeSet == 1) {
dp[mask][firstSetBit] = 1;
}
else {
for ( int j = firstSetBit + 1;
j < N; j++) {
if ((mask & (1 << j))) {
int newNodeSet = mask ^ (1 << j);
for ( int k = 0; k < N; k++) {
if ((newNodeSet & (1 << k))
&& adj[k][j]) {
dp[mask][j]
+= dp[newNodeSet][k];
if (adj[j][firstSetBit]
&& nodeSet > 2)
ans += dp[mask][j];
}
}
}
}
}
}
cout << ans << endl;
}
int main()
{
vector<vector< int > > adj
= { { 0, 1, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 0, 1 },
{ 1, 0, 1, 0 } };
int N = adj.size();
findNumberOfSimpleCycles(N, adj);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int __builtin_popcountll( long x)
{
int setBits = 0 ;
while (x != 0 ) {
x = x & (x - 1 );
setBits++;
}
return setBits;
}
static int getFirstSetBitPos( int n)
{
return ( int )((Math.log10(n & -n)) / Math.log10( 2 )) + 1 ;
}
static void findNumberOfSimpleCycles(
int N, int [][] adj)
{
int ans = 1 ;
int [][]dp = new int [( 1 << N)][N];
for ( int mask = 0 ;
mask < ( 1 << N); mask++) {
int nodeSet
= __builtin_popcountll(mask);
int firstSetBit
= getFirstSetBitPos(mask);
if (nodeSet == 1 ) {
dp[mask][firstSetBit- 1 ] = 1 ;
}
else {
for ( int j = firstSetBit + 1 ;
j < N; j++) {
if ((mask & ( 1 << j))!= 0 ) {
int newNodeSet = mask ^ ( 1 << j);
for ( int k = 0 ; k < N; k++) {
if ((newNodeSet & ( 1 << k)) != 0
&& adj[k][j] != 0 ) {
dp[mask][j]
+= dp[newNodeSet][k];
if (adj[j][firstSetBit]!= 0
&& nodeSet > 2 )
ans += dp[mask][j];
}
}
}
}
}
}
System.out.print(ans + "\n" );
}
public static void main(String[] args)
{
int [][] adj
= { { 0 , 1 , 1 , 1 },
{ 1 , 0 , 1 , 0 },
{ 1 , 1 , 0 , 1 },
{ 1 , 0 , 1 , 0 } };
int N = adj.length;
findNumberOfSimpleCycles(N, adj);
}
}
|
Python3
import math
def __builtin_popcountll(num):
binary = bin (num)
setBits = [ones for ones in binary[ 2 :] if ones = = '1' ]
return len (setBits)
def __builtin_ffsl(n):
if n = = 0 :
return 0
return math.floor(math.log2(n & - n)) + 1
def findNumberOfSimpleCycles(N, adj):
ans = 1
dp = []
for i in range ( 0 , ( 1 << N)):
dp.append([])
for j in range ( 0 , N):
dp[i].append( 0 )
for i in range ( 0 , ( 1 << N)):
for j in range ( 0 , N):
if (dp[i][j] ! = 0 ):
print (dp[i][j], i, j)
for mask in range ( 0 , ( 1 << N)):
nodeSet = __builtin_popcountll(mask)
firstSetBit = __builtin_ffsl(mask)
if (nodeSet = = 1 ):
dp[mask][firstSetBit - 1 ] = 1
else :
for j in range (firstSetBit + 1 , N):
if (mask & ( 1 << j)) ! = 0 :
newNodeSet = mask ^ ( 1 << j)
for k in range ( 0 , N):
if (((newNodeSet & ( 1 << k)) > 0 ) and adj[k][j] > 0 ):
dp[mask][j] + = dp[newNodeSet][k]
if ((adj[j][firstSetBit] > 0 ) and nodeSet > 2 ):
ans + = dp[mask][j]
print (ans)
if __name__ = = '__main__' :
adj = [ [ 0 , 1 , 1 , 1 ],
[ 1 , 0 , 1 , 0 ],
[ 1 , 1 , 0 , 1 ],
[ 1 , 0 , 1 , 0 ] ]
N = len (adj)
findNumberOfSimpleCycles(N, adj)
|
C#
using System;
public class GFG{
static int __builtin_popcountll( long x)
{
int setBits = 0;
while (x != 0) {
x = x & (x - 1);
setBits++;
}
return setBits;
}
static int getFirstSetBitPos( int n)
{
return ( int )((Math.Log10(n & -n)) / Math.Log10(2)) + 1;
}
static void findNumberOfSimpleCycles(
int N, int [,] adj)
{
int ans = 1;
int [,]dp = new int [(1 << N),N];
for ( int mask = 0;
mask < (1 << N); mask++) {
int nodeSet
= __builtin_popcountll(mask);
int firstSetBit
= getFirstSetBitPos(mask);
if (nodeSet == 1) {
dp[mask,firstSetBit-1] = 1;
}
else {
for ( int j = firstSetBit + 1;
j < N; j++) {
if ((mask & (1 << j))!=0) {
int newNodeSet = mask ^ (1 << j);
for ( int k = 0; k < N; k++) {
if ((newNodeSet & (1 << k)) !=0
&& adj[k,j] !=0) {
dp[mask,j]
+= dp[newNodeSet,k];
if (adj[j,firstSetBit]!=0
&& nodeSet > 2)
ans += dp[mask,j];
}
}
}
}
}
}
Console.Write(ans + "\n" );
}
public static void Main(String[] args)
{
int [,] adj
= { { 0, 1, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 0, 1 },
{ 1, 0, 1, 0 } };
int N = adj.GetLength(0);
findNumberOfSimpleCycles(N, adj);
}
}
|
Javascript
<script>
function __builtin_popcountll(x)
{
var setBits = 0;
while (x != 0) {
x = x & (x - 1);
setBits++;
}
return setBits;
}
function getFirstSetBitPos(n)
{
return parseInt(((Math.log10(n & -n)) / Math.log10(2)) + 1);
}
function findNumberOfSimpleCycles(
N, adj)
{
var ans = 1;
var dp = Array(1 << N).fill().map(()=>Array(N).fill(0));
for ( var mask = 0;
mask < (1 << N); mask++) {
var nodeSet
= __builtin_popcountll(mask);
var firstSetBit
= getFirstSetBitPos(mask);
if (nodeSet == 1) {
dp[mask][firstSetBit-1] = 1;
}
else {
for (j = firstSetBit + 1;
j < N; j++) {
if ((mask & (1 << j))!=0) {
var newNodeSet = mask ^ (1 << j);
for (k = 0; k < N; k++) {
if ((newNodeSet & (1 << k)) !=0
&& adj[k][j] !=0) {
dp[mask][j]
+= dp[newNodeSet][k];
if (adj[j][firstSetBit]!=0
&& nodeSet > 2)
ans += dp[mask][j];
}
}
}
}
}
}
document.write(ans + "\n" );
}
var adj
= [ [ 0, 1, 1, 1 ],
[ 1, 0, 1, 0 ],
[ 1, 1, 0, 1 ],
[ 1, 0, 1, 0 ] ];
var N = adj.length;
findNumberOfSimpleCycles(N, adj);
</script>
|
Time Complexity: O((2N)N2)
Auxiliary Space: O(1)
Last Updated :
15 Jun, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...