题目:http://codeforces.com/problemset/problem/11/D
题意:给定一个图,求图中环的数目
为了消除重复计算,我们要从每个点出发,并将这个点作为环的最小点,再次回到出发点时就变成了环
但是这样依然有重复,会有1条边重复走2次的环,同时还会将大于3的环正向跑一遍逆向跑一遍
所以最后答案需要-m再除2
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; int a[25][25]; long long dp[1<<19][19]; int main() { int n,m; scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); x--;y--; a[x][y]=a[y][x]=1; } memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) dp[1<<i][i]=1; int tot=1<<n; long long ans=0; for(int st=0;st<tot;st++) { for(int i=0;i<n;i++) { if (dp[st][i]==0) continue; for(int j=0;j<n;j++) if (a[i][j]) { if ((st&-st)>1<<j) continue; if (st>>j&1) { if ((st&-st)==1<<j) ans+=dp[st][i]; } else dp[st|1<<j][j]+=dp[st][i]; } } } ans=(ans-m)>>1; printf("%lld ",ans); return 0; }