[CF11D] A Simple Task

題目

求無向圖的簡單環個數,點數不大於19c++

 

題解

根據數據範圍很容易得知是狀壓dp,廣泛想法是記錄點數狀態和最後一個點再進行延伸,但這樣很是容易重複。ide

咱們能夠考慮將一個狀態裏最低的一位設爲起點,每次只向高位進行延伸。最後判一下起點與終點是否相連,更新答案。(簡稱拆環成鏈)ui

注意這樣仍是有重複的,一個環順時針逆時針會個算一次,除以二就行了。spa

 

代碼

#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
相關文章
相關標籤/搜索