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 and m (1 ≤ n ≤ 19, 0 ≤ m) – respectively the number of vertices and edges of the graph. Each of the subsequent m lines contains two integers a and b, (1 ≤ a, b ≤ n, a ≠ b) indicating that vertices a and 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.
题意:
求一个图中(节点个数小于20)长度大于等于三的哈密顿路径数目。
思路:
点数不多,类似TSP,用状压dp解决。
dp[i][j]表示状态为i时,以j结尾的路径条数。
如果下一个点能回到已经走过的一个点中,那么就是一个回路了。
为了避免重复计算,回到的点为走过的最小的点。(这是一个优化,少了枚举最小点这个循环)
长度为2的哈密顿路径会计算到,可以不做处理,最后减去边的条数即可,每个环会算两遍,最后要除以2.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 205
#define MAXN 100005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
ll n,m,ans,flag,cnt,tot;
ll mp[20][20],dp[1<<19][19];
int first(int s)
{
for(int i=0;i<n;i++)
{
if(s&(1<<i)) return i;
}
}
void solve()
{
ll i,j,t,k,p,u,v,s;
ans=0;
tot=(1<<n)-1;
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++)
{
dp[1<<i][i]=1;
}
for(i=1; i<=tot; i++)
{
for(j=0; j<n; j++)
{
if(dp[i][j]==0) continue ;
p=first(i);
for(k=p; k<n; k++)
{
if(j==k||mp[j][k]==0) continue ;
if(i&(1<<k))
{
if(k==p) ans+=dp[i][j];
}
else
{
s=i|(1<<k);
dp[s][k]+=dp[i][j];
}
}
}
}
ans-=m;
ans/=2;
printf("%I64d\n",ans);
}
int main()
{
ll i,j,t;
while(~scanf("%I64d%I64d",&n,&m))
{
memset(mp,0,sizeof(mp));
ll u,v;
for(i=1; i<=m; i++)
{
scanf("%I64d%I64d",&u,&v);
u--,v--;
mp[u][v]=mp[v][u]=1;
}
solve();
}
return 0;
}