首页 > 其他 > 详细

[CF11D] A Simple Task

时间:2020-12-12 23:37:04      阅读:47      评论:0      收藏:0      [点我收藏+]

题目

求无向图的简单环个数,点数不大于19

 

题解

根据数据范围很容易得知是状压dp,普遍想法是记录点数状态和最后一个点再进行延伸,但这样非常容易重复。

我们可以考虑将一个状态里最低的一位设为起点,每次只向高位进行延伸。最后判一下起点与终点是否相连,更新答案。(简称拆环成链)

注意这样还是有重复的,一个环顺时针逆时针会个算一次,除以二就好了。

 

代码

技术分享图片
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int MAXN=20;
const int MAXM=(1<<19)+5;

int N,M;
int mp[MAXN][MAXN];
LL dp[MAXM][MAXN];

int main(){
    scanf("%d%d",&N,&M);
    for(int i=1,u,v;i<=M;i++){
        scanf("%d%d",&u,&v);
        u--;v--;
        mp[u][v]=mp[v][u]=1;
    }
    LL ans=0;
    for(int i=0;i<N;i++) dp[1<<i][i]=1;
    for(int mask=1;mask<(1<<N);mask++){
        int st=0;
        for(;st<N;st++)if((mask>>st)&1) break;
        for(int en=st;en<N;en++)if(dp[mask][en]){
            for(int i=st+1;i<N;i++)if(!((mask>>i)&1)){
                if(!mp[en][i]) continue;
                dp[mask|(1<<i)][i]+=dp[mask][en];
                if(mp[i][st]&& __builtin_popcount(mask|(1<<i)) >= 3) ans+=dp[mask][en];
            }
        }
    }
    printf("%lld",ans/2);
    return 0;
} 
View Code

 

[CF11D] A Simple Task

原文:https://www.cnblogs.com/EDawnpractice/p/14126883.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!