状态压缩DP 求简单图的环的个数
题目链接http://www.codeforces.com/contest/11/problem/D
题目的点数不超过20,所以利用状态压缩DP可解
dp[i][j]表示i状态时以j结尾的简单路径的数量,i的二进制表示中为1的表示这个点在路径中
i的二进制中最低位1表示的点是起始点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio>
#include<cstring>
typedef __int64 lld;
const int maxn = 19;
lld dp[1<<maxn][maxn];//
int mp[maxn][maxn];
int main(){
int n,m,a,b,i,j,k;
while(scanf("%d%d",&n,&m)!=EOF){
memset(mp,0,sizeof(mp));
while(m--){
scanf("%d%d",&a,&b);
a--;b--;
mp[a][b]=mp[b][a]=1;
}
for(i=0;i<(1<<n);i++) for(j=0;j<n;j++) dp[i][j]=0;
for(i=0;i<n;i++) dp[1<<i][i]=1;
lld ans=0;
for(i=0;i<(1<<n);i++){
for(j=0;j<n;j++){
if(!dp[i][j]) continue;
bool flag=0;
for(k=0;k<n;k++){
if((1<<k)&i){
if(!flag&&mp[j][k]&&i!=((1<<j)+(1<<k))){//如果是起始点,且和结束点相连,且点集中至少有三个点,则构成了环
ans+=dp[i][j];
}
flag=1;
}
else if(flag && mp[j][k])
dp[i^(1<<k)][k]+=dp[i][j];
}
}
}
printf("%I64d\n",ans>>1);
}
return 0;
}