📜  具有 N 个顶点的无向图中的简单循环计数

📅  最后修改于: 2022-05-13 01:56:04.343000             🧑  作者: Mango

具有 N 个顶点的无向图中的简单循环计数

给定邻接矩阵adj[][]形式的N个顶点的无向无权图,任务是找出其中的简单循环数。

方法:给定的问题可以通过使用带有位掩码的动态规划来解决,哈密顿路径的动态规划状态定义为dp[mask][i]作为覆盖节点集掩码并在i处结束的路径数并从0迭代到N-1并在每次迭代中,计算包含当前节点但不包含前一个节点的循环数并将它们相加,因为循环有两个方向,所以将结果除以2 。请按照以下步骤解决问题:

  • 将变量ans初始化为0 ,用于存储循环的结果计数。
  • 初始化一个二维数组dp[][]维度为2 NN的数组,并用0对其进行初始化。
  • 使用变量掩码迭代范围[0, 2 N – 1)并执行以下任务:
    • 将 2 个变量nodeSetfirstSetBit初始化为设置位的数量和mask中的第一个设置位。
    • 如果nodeSet等于1,则将dp[mask][firstSetBit]的值设置为1
    • 现在,对于每个设置位大于1的掩码,使用变量j迭代范围[firstSetBit + 1, N – 1) ,如果掩码和 2 j的按位与为,则将变量newNodeSet初始化为掩码^ 2 j并使用变量k迭代范围[0, N)并执行以下任务:
      • 检查节点kj之间是否存在边( k不等于j)
      • 如果有一条边,则将该掩码中以k结尾且不包含j的循环数添加到节点集掩码的状态中,如下所示dp[mask][j] = dp[mask][j]+ dp[掩码 XOR 2 j ][k]
      • 如果adj[j][firstSetBit]1nodeSet大于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)