列表

详情


NC16544. 简单环

描述

给定一张n个点m条边的无向图,求出图中所有简单环的数量。(简单环:简单环又称简单回路,图的顶点序列中,除了第一个顶点和最后一个顶点相同外,其余顶点不重复出现的回路叫简单回路。或者说,若通路或回路不重复地包含相同的边,则它是简单的)

输入描述

第一行三个数n m k (k在输出描述中提到)
接下来m行每行两个数u,v表示u到v之间存在一条边(无重边)

输出描述

输出k行每行1个整数
第i个数表示长度%k==i-1的简单环的数量(对998244353取模)
(只记录长度大于2的简单环的数量)

示例1

输入:

4 6 3
1 2
2 3
3 4
4 1
2 4
1 3

输出:

4
3
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1317ms, 内存消耗: 90744K, 提交时间: 2018-06-09 15:36:15

#include<bits/stdc++.h>
#define MAXN 2000005
#define P 998244353
#define ll long long
using namespace std;
bool b[20][20];
int f[1048576][20],i,j,k,n,m,N,ans[20],o[1048576],w[1048576];
int main()
{
    for(i=2;i<1048576;i++)o[i]=o[i>>1]+1;
    cin>>n>>m>>N;
    while(m--)
    {
        cin>>i>>j;
        i--;
        j--;
        b[i][j]=b[j][i]=1;
    }
    for(i=0;i<n;i++)f[1<<i][i]=1;
    for(i=1;i<1<<n;i++)
	for(j=0;j<=o[i];j++)if(i>>j&1)
	for(k=0;k<o[i];k++)if(!(i>>k&1)&&b[j][k])
    {
        f[i|1<<k][k]+=f[i][j];
        if(f[i|1<<k][k]>=P)f[i|1<<k][k]-=P;
    }
    for(i=1;i<1<<n;i++)
    {
        w[i]=w[i>>1]+(i&1);
        if(w[i]>=3)for(j=0;j<o[i];j++)if((i>>j&1)&&b[o[i]][j])
        {
            ans[w[i]%N]+=f[i][j];
            if(ans[w[i]%N]>=P)ans[w[i]%N]-=P;
        }
    }
    for(i=0;i<N;i++)cout<<(ll)ans[i]*(P+1)/2%P<<endl;
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 1155ms, 内存消耗: 62124K, 提交时间: 2022-08-24 23:22:38

#include<bits/stdc++.h>
using namespace std;
const int N=21,P=998244353; int n,m,k,a[N][N],f[N][1<<N],g[N],h[N];
int main() {
	int i,j,p,q,x,y;
	scanf("%d%d%d",&n,&m,&k);
	for (i=1;i<=m;i++) {
		scanf("%d%d",&x,&y);
		if (x!=y) a[x][y]=a[y][x]=1;
	}
	for (i=1;i<=n;i++) f[i][1<<i-1]=1;
	for (j=1;j<=(1<<n);j++) {
		for (i=1;i<=n;i++)
			if (j&(1<<i-1)) {p=i; break;}
		for (i=1;i<=n;i++)
			if (f[i][j]) {
				if (a[i][p]) q=__builtin_popcount(j),g[q]=(g[q]+f[i][j])%P;
				for (q=p+1;q<=n;q++)
					if (a[i][q]&&!(j&(1<<q-1)))
						f[q][j^(1<<q-1)]=(f[q][j^(1<<q-1)]+f[i][j])%P;
			}
	}
	for (i=3;i<=n;i++) h[i%k]=(h[i%k]+g[i])%P;
	for (i=0;i<k;i++) printf("%d\n",(1ll*h[i]*((P+1)/2))%P);
}

上一题