Codeforces 11D A Simple Task (状态压缩DP)

来源:互联网 发布:php substr 中文乱码 编辑:程序博客网 时间:2024/05/13 18:21

给你N个点和M条边,求当中包含的简单路径的个数。

网上看的题解,其实就是求哈密顿回路数,但是是无向图而且至少由三个点组成。

http://codeforces.com/blog/entry/337

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;typedef long long ll;const ll maxm=1<<19;ll dp[maxm][20],sum;int lowbit[maxm];bool map[20][20];int n,m,u,v,start;inline bool bt(int i,int mask){    return mask&(1<<i);}inline int cnt(int mask){    int ret=0;    while(mask) ret+=(mask&1),mask>>=1;    return ret;}void getfirst(){    int i;    for(i=1; i<maxm; i++)    {        int mask=i,ret=0;        while(mask&1^1) ret++,mask>>=1;        lowbit[i]=ret;    }}ll dfs(int mask,int end){    int j,tmp=cnt(mask);    ll ans=0;    if(dp[mask][end]>=0) return dp[mask][end];    for(j=start; j<n; j++)        if(j!=end&&bt(j,mask)&&map[j][end]&&(tmp==2||j!=start))            ans+=dfs(mask^(1<<end),j);    if(tmp>2&&map[end][start])//当前搜索的end点和起始点相连并且含有3个点以上        sum+=ans;    return dp[mask][end]=ans;}int main(){    int i;    getfirst();    memset(dp,-1,sizeof(dp));    memset(map,0,sizeof(map));    cin>>n>>m;    sum=0;    while(m--)    {        cin>>u>>v;        u--,v--;        map[u][v]=map[v][u]=1;    }    for(i=0; i<n; i++) dp[1<<i][i]=1;    int maxmask=1<<n;    for(int mask=0; mask<maxmask; mask++)        if(cnt(mask)>1)        {            start=lowbit[mask];            for(i=start; i<n; i++)                if(bt(i,mask)&&map[start][i])                    dfs(mask,i);        }    cout<<sum/2<<endl;    return 0;}


原创粉丝点击