原题链接
求无向图中的简单环个数,保证不存在重边和自环。
简单环:除起点外,其余的点都只出现一次的回路。
Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices or edges.
The first line of input contains two integers n n n and m m m ( 1 ≤ n ≤ 19 1\le n\le19 1≤n≤19 , 0 ≤ m 0\le m 0≤m ) – respectively the number of vertices and edges of the graph. Each of the subsequent $ m $ lines contains two integers a a a and b b b , ( 1 ≤ a , b ≤ n 1\le a,b\le n 1≤a,b≤n , a ≠ b a≠b a=b ) indicating that vertices a a a and b b b are connected by an undirected edge. There is no more than one edge connecting any pair of vertices.
Output the number of cycles in the given graph.
4 6
1 2
1 3
1 4
2 3
2 4
3 4
7
The example graph is a clique and contains four cycles of length 3 and three cycles of length 4.
考虑用状压DP:
令 f [ j ] [ i ] f[j][i] f[j][i] 表示 n n n 个节点走过的状态,起点为 i i i 中最小的 1 1 1 的位置,且终点为 j j j 的路径总数。
考虑转移方程: f [ j ] [ i ] f[j][i] f[j][i] 转移至 f [ k ] [ i ∣ ( 1 < < ( k − 1 ) ) ] f[k][i|(1<<(k-1))] f[k][i∣(1<<(k−1))],由题可得是直接累加的,但必须满足以下条件:
那么如果已经有了 k k k 这个点且 k k k 就为起点,那就是找到环了,直接统计即可。
注意:
f[i][1<<(i-1)]=1;
即出发的点。
if(i&(1<<(k-1)))
{
if(lowbit(i)==(1<<(k-1)))
ans+=f[j][i];
}
else
f[k][i|(1<<(k-1))]+=f[j][i];
#include
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);
using namespace std;
const int N=1<<19;
int f[20][N],n,m,x,y,a[101][101],ans;
inline int lowbit(int x)
{
return x&-x;
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>x>>y,a[x][y]=a[y][x]=1;
for(int i=1;i<=n;i++)
f[i][1<<(i-1)]=1;
for(int i=0;i<(1<<n);i++)
{
for(int j=1;j<=n;j++)
{
if(!f[j][i])
continue;
for(int k=1;k<=n;k++)
{
if(!a[j][k])
continue;
if(lowbit(i)>(1<<(k-1)))
continue;
if(i&(1<<(k-1)))
{
if(lowbit(i)==(1<<(k-1)))
ans+=f[j][i];
}
else
f[k][i|(1<<(k-1))]+=f[j][i];
}
}
}
cout<<(ans-m)/2;
return 0;
}
更多方法