具有 N 个顶点的无向图中的简单循环计数
给定邻接矩阵adj[][]形式的N个顶点的无向无权图,任务是找出其中的简单循环数。
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
方法:给定的问题可以通过使用带有位掩码的动态规划来解决,哈密顿路径的动态规划状态定义为dp[mask][i]作为覆盖节点集掩码并在i处结束的路径数并从0迭代到N-1并在每次迭代中,计算包含当前节点但不包含前一个节点的循环数并将它们相加,因为循环有两个方向,所以将结果除以2 。请按照以下步骤解决问题:
- 将变量ans初始化为0 ,用于存储循环的结果计数。
- 初始化一个二维数组dp[][]维度为2 N和N的数组,并用0对其进行初始化。
- 使用变量掩码迭代范围[0, 2 N – 1)并执行以下任务:
- 将 2 个变量nodeSet和firstSetBit初始化为设置位的数量和mask中的第一个设置位。
- 如果nodeSet等于1,则将dp[mask][firstSetBit]的值设置为1 。
- 现在,对于每个设置位大于1的掩码,使用变量j迭代范围[firstSetBit + 1, N – 1) ,如果掩码和 2 j的按位与为真,则将变量newNodeSet初始化为掩码^ 2 j并使用变量k迭代范围[0, N)并执行以下任务:
- 检查节点k和j之间是否存在边( k不等于j) 。
- 如果有一条边,则将该掩码中以k结尾且不包含j的循环数添加到节点集掩码的状态中,如下所示dp[mask][j] = dp[mask][j]+ dp[掩码 XOR 2 j ][k] 。
- 如果adj[j][firstSetBit]为1且nodeSet大于2,则将dp[mask][j]的值添加到变量ans中。
- 执行上述步骤后,打印ans的值作为答案。
下面是上述方法的实现。
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the number of simple
// cycles in an undirected unweighted graph
void findNumberOfSimpleCycles(
int N, vector > adj)
{
// Stores the count of cycles
int ans = 0;
int dp[(1 << N)][N];
// Initialize it with 0
memset(dp, 0, sizeof dp);
// Iterate over all subsets
for (int mask = 0;
mask < (1 << N); mask++) {
// Find the number of set bits
int nodeSet
= __builtin_popcountll(mask);
// Find the first set bit
int firstSetBit
= __builtin_ffsl(mask);
// If the nodeSet contains only
// 1 set bit
if (nodeSet == 1) {
// Initialize it with 1
dp[mask][firstSetBit] = 1;
}
else {
// Iterate over all bits
// of the mask
for (int j = firstSetBit + 1;
j < N; j++) {
// Check if the bit is set
// and is not the first node
if ((mask & (1 << j))) {
// Remove this bit and
// compute the node set
int newNodeSet = mask ^ (1 << j);
// Iterate over the masks
// not equal to j
for (int k = 0; k < N; k++) {
// If the kth bit is set &
// there is an edge from k to j
if ((newNodeSet & (1 << k))
&& adj[k][j]) {
dp[mask][j]
+= dp[newNodeSet][k];
// If the first node is
// connected with the jth
if (adj[j][firstSetBit]
&& nodeSet > 2)
ans += dp[mask][j];
}
}
}
}
}
}
// Print the answer
cout << ans << endl;
}
// Driver Code
int main()
{
// Given input graph in the form
// of adjacency matrix
vector > adj
= { { 0, 1, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 0, 1 },
{ 1, 0, 1, 0 } };
// Number of vertices in the graph
int N = adj.size();
findNumberOfSimpleCycles(N, adj);
return 0;
}
Java
// Java program for the above approach
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;
}
// Function to find the number of simple
// cycles in an undirected unweighted graph
static void findNumberOfSimpleCycles(
int N, int[][] adj)
{
// Stores the count of cycles
int ans = 1;
int [][]dp = new int[(1 << N)][N];
// Iterate over all subsets
for (int mask = 0;
mask < (1 << N); mask++) {
// Find the number of set bits
int nodeSet
= __builtin_popcountll(mask);
// Find the first set bit
int firstSetBit
= getFirstSetBitPos(mask);
// If the nodeSet contains only
// 1 set bit
if (nodeSet == 1) {
// Initialize it with 1
dp[mask][firstSetBit-1] = 1;
}
else {
// Iterate over all bits
// of the mask
for (int j = firstSetBit + 1;
j < N; j++) {
// Check if the bit is set
// and is not the first node
if ((mask & (1 << j))!=0) {
// Remove this bit and
// compute the node set
int newNodeSet = mask ^ (1 << j);
// Iterate over the masks
// not equal to j
for (int k = 0; k < N; k++) {
// If the kth bit is set &
// there is an edge from k to j
if ((newNodeSet & (1 << k)) !=0
&& adj[k][j] !=0) {
dp[mask][j]
+= dp[newNodeSet][k];
// If the first node is
// connected with the jth
if (adj[j][firstSetBit]!=0
&& nodeSet > 2)
ans += dp[mask][j];
}
}
}
}
}
}
// Print the answer
System.out.print(ans +"\n");
}
// Driver Code
public static void main(String[] args)
{
// Given input graph in the form
// of adjacency matrix
int[][] adj
= { { 0, 1, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 0, 1 },
{ 1, 0, 1, 0 } };
// Number of vertices in the graph
int N = adj.length;
findNumberOfSimpleCycles(N, adj);
}
}
// This code is contributed by umadevi9616
C#
// C# program for the above approach
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;
}
// Function to find the number of simple
// cycles in an undirected unweighted graph
static void findNumberOfSimpleCycles(
int N, int[,] adj)
{
// Stores the count of cycles
int ans = 1;
int [,]dp = new int[(1 << N),N];
// Iterate over all subsets
for (int mask = 0;
mask < (1 << N); mask++) {
// Find the number of set bits
int nodeSet
= __builtin_popcountll(mask);
// Find the first set bit
int firstSetBit
= getFirstSetBitPos(mask);
// If the nodeSet contains only
// 1 set bit
if (nodeSet == 1) {
// Initialize it with 1
dp[mask,firstSetBit-1] = 1;
}
else {
// Iterate over all bits
// of the mask
for (int j = firstSetBit + 1;
j < N; j++) {
// Check if the bit is set
// and is not the first node
if ((mask & (1 << j))!=0) {
// Remove this bit and
// compute the node set
int newNodeSet = mask ^ (1 << j);
// Iterate over the masks
// not equal to j
for (int k = 0; k < N; k++) {
// If the kth bit is set &
// there is an edge from k to j
if ((newNodeSet & (1 << k)) !=0
&& adj[k,j] !=0) {
dp[mask,j]
+= dp[newNodeSet,k];
// If the first node is
// connected with the jth
if (adj[j,firstSetBit]!=0
&& nodeSet > 2)
ans += dp[mask,j];
}
}
}
}
}
}
// Print the answer
Console.Write(ans +"\n");
}
// Driver Code
public static void Main(String[] args)
{
// Given input graph in the form
// of adjacency matrix
int[,] adj
= { { 0, 1, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 0, 1 },
{ 1, 0, 1, 0 } };
// Number of vertices in the graph
int N = adj.GetLength(0);
findNumberOfSimpleCycles(N, adj);
}
}
// This code is contributed by gauravrajput1
Javascript
输出:
2
时间复杂度: O((2 N )N 2 )
辅助空间: O(1)