CodeForces 11D A Simple Task (DP解哈密顿路径数目)

D. A Simple Task
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices or edges.

Input

The first line of input contains two integers n and m (1 ≤ n ≤ 190 ≤ 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 ≤ na ≠ 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

Output the number of cycles in the given graph.

Sample test(s)
input
4 6
1 2
1 3
1 4
2 3
2 4
3 4
output
7
Note

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;
}


posted on 2017-05-24 17:27  ljbguanli  阅读(211)  评论(0编辑  收藏  举报