代码参考https://www.luogu.org/blog/812-xiao-wen/solution-cf11d,感谢大佬的讲解。
#include<bits/stdc++.h> #define ll long long using namespace std; int n,m,t,u,v; bool a[20][20];//邻接矩阵 ll ans,f[600001][20];//dp数组,第一维记录点的状态,第二维记录起点 int main(){ cin>>n>>m; t=1<<n; for(int i=1;i<=m;++i){ cin>>u>>v; u--; v--; a[u][v]=a[v][u]=1; } for(int i=0;i<n;++i) f[1<<i][i]=1;//初始化
for(int i=1;i<=t;++i){ for(int j=0;j<n;++j){ if(!f[i][j])continue; for(int k=0;k<n;++k){ if(!a[j][k])continue;//如果不存在边,跳过 if((i&-i)>(1<<k))continue;//如果起点不是k,跳过//这里i&-i取得的是起点 if(1<<k&i){//如果这个点在里面 if(1<<k==(i&-i))//如果k就是起点,加入答案 ans+=f[i][j]; } else f[i|1<<k][k]+=f[i][j];//不在里面就加进入 } } } cout<<(ans-m)/2<<endl;//注意去重和两点成环的非法情况 return 0; }