A Simple Task

  • 环计数问题
  • __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;
}
posted @ 2025-02-01 19:45  D06  阅读(31)  评论(0)    收藏  举报
//雪花飘落效果