这道题的数据范围一看就是dfs或状压啦~
本文以状压的方式来讲解
f[i][j]表示目前的节点是i,已经经历过的节点的状态为j的简单环的个数;
具体的转移方程和细节请看代码;
PS:(i&-i)的意义便是树状数组
#include <bits/stdc++.h> using namespace std; int n,m; int a[20][20]; long long f[20][1000010]; long long ans; int main () { cin>>n>>m; for(register int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); a[u][v]=1; a[v][u]=1; } for(int i=1;i<=n;i++) f[i][1<<(i-1)]=1; for(int i=1;i<=1<<(n);i++){ //状态,其中i&-i是起点 for(int j=1;j<=n;j++){ //n^2枚举点 for(int k=1;k<=n;k++){ if(!a[j][k]) continue; if((i&-i)>1<<(k-1)) continue; //如果这个点回到了比起点还起点的点,那么就违规了; if(1<<(k-1)&i){ //如果这个点已经遍历过 if(1<<(k-1)==(i&-i)){ //如果这个点k是状态i的起点(代表又一次回到了起点) ans+=f[j][i]; } else{ continue; } } else{ f[k][i|(1<<(k-1))]+=f[j][i]; } } } } cout<<(ans-m)/2; }