- 环计数问题
- __builtin_ffs() 函数 find_first_set 返回最后一个1的位置,注意编号从1开始
- 构造汉明权重递增的排列 核心思想:枚举popcount+不断迭代
- 迭代方法:
for(int j=(1<<m)-1,t;j<(1<<n);t=j+lowbit(j),j=t|(((lowbit(t)/lowbit(j))>>1)-1))
- 至于这道题,选择编号最小的节点作为简单环的代表就好啦
#include <bits/stdc++.h>
using namespace std;
vector<int>a[19];
long long f[19][1<<19];
bool b[19][19];
int lowbit(int n)
{return n&(-n);
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);int n,m;cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;u--;v--;a[u].push_back(v);a[v].push_back(u);b[u][v]=b[v][u]=true;}for(int i=0;i<n;i++){sort(a[i].begin(),a[i].end());reverse(a[i].begin(),a[i].end());f[i][1<<i]=1;}long long ans=0;for(int m=2;m<=n;m++){for(int j=(1<<m)-1,t;j<(1<<n);t=j+lowbit(j),j=t|(((lowbit(t)/lowbit(j))>>1)-1)){int i=__builtin_ffs(j)-1;for(int k=i,s=j;s>0;s=s-lowbit(s),k=__builtin_ffs(s)-1){if(k==i){continue;}if((j>>k)&1){int p=(j&(~(1<<k)));for(int l=0;l<a[k].size();l++){if(a[k][l]<i){break;}if((j>>a[k][l])&1){f[k][j]+=f[a[k][l]][p];}}if(b[i][k]&&m>2){ans+=f[k][j];}}}}}cout<<ans/2<<endl;return 0;
}