P4727 [HNOI2009]图的同构记数 题解

P4727 [HNOI2009]图的同构记数 题解

题意:求n个点的无标号简单无向图有多少种。n<=60

首先我们容易知道n个点的有标号无向图个数是\(2^{\frac{n*(n-1)}{2}}\)的,但是这些图中有很多是同构的,我们要把这些同构的排除掉。也就是说,所有的标号无向图根据是否同构分成了若干等价类,我们就是要统计其中等价类的个数。而对于两个有标号无向图,它们同构的充要条件是存在一个排列\(P_i\),使得第一个图中的所有点i换到原来\(P_i\)的位置上后它与第二个图完全一样。

那么我们就建立了一个模型,我们手上有一个由所有的有标号无向图组成的集合,我们还有一个置换群,其中包含所有的排列,如果一个集合中的一个元素可以经过置换得到另一个元素,那么这两个元素就在同一个等价类里面,问可以把这个集合分成多少个等价类。

这个问题很显然可以用Burnside引理解决,具体地,设置换群为\(G\)\(C(P_i)\)为置换\(P_i\)下有多少个有标号无向图经过这个置换后还是它本身,那么我们的等价类个数:

\[L=\sum_{P_i\in G}\frac{C(P_i)}{|G|} \]

我们看要怎么计算不动点个数,首先每个有标号无向图都可以由它的边集\(\{(u,v)\}\)唯一表示,那么一张图经过置换\(P_i\)后还是它本身等价于\(\{(P_u,P_v)\}=\{(u,v)\}\) ,也就是\(\forall (u,v)\in E,(P_u,P_v)\in E\)

怎么计算满足这样条件的图的个数呢?我们知道,一个置换可以被分解为若干个循环(Burnside常用套路),那么上面的限制条件相当于如果两个点之间有连边,那么它们所在循环的下一个点之间也要有连边,相当于一开始第一个循环的第i个位置和第二个循环的第j个位置有连边,那么接下来令i++,j++,继续在i和j之间连边,如此循环下去,可以发现一共会连出两个环长的lcm条边,那么这些边相当于只有两种选择:要么都不连,要么全都连。并且这样的边一共有gcd(环长组),那么连边的总方案数为\(2^{gcd}\),将这些环两两之间连边的方案数乘起来,再乘以每个环内部连边的方案数(为\(2^{\lfloor\frac{s}{2}\rfloor}\),其中s为这个环的环长),那么就得到了这个置换下的不动点个数。

但是我们是不能枚举每个置换来计算的,这样的复杂度是\(O(n!)\)的,但是我们发现一种置换的贡献只与它分解出来的所有环的环长有关,我们可以枚举每个环的环长,然后可以计算将这n个点划分到这几个环中的方案数,然后对于一种划分,我们又可以计算它对应的置换的个数,这样就可以对所有本质相同的置换合并算贡献了。

具体的,所有置换下不动点个数之和为:

\[\sum_{s_1\leq s_2...\leq s_m,s_1+s_2...+s_m=n}\frac{n!}{\prod s_i!}\frac{1}{\prod_{k=1}^{n}(\sum_{i=1}^m [s_i=k])!}\prod(s_i-1)!*\prod 2^{\lfloor\frac{s_i}{2}\rfloor}*\prod_{i=1}^m\prod_{j=i+1}^m2^{gcd(s_i,s_j)} \]

最后再除以置换群的大小\(n!\)就是答案。

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 107
const int mod=997;
int inv[N],gd[N][N],po[N];
int a[N],n,res,c[N];
int p2(int x){return x*x%mod;}
int pw(int x,int p)
{
    return p?p2(pw(x,p/2))*(p&1?x:1)%mod:1;
}
int gcd(int x,int y)
{
    return y?gcd(y,x%y):x;
}
void init()
{
    inv[1]=1;
    for(int i=2;i<=n;i++)
		inv[i]=mod-mod/i*inv[mod%i]%mod;
    for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
	    	gd[i][j]=gcd(i,j);
    po[0]=1;
    for(int i=1;i<=n;i++)po[i]=po[i-1]*2%mod;
}
void dfs(int x,int d,int s,int ans)
{
    if(s==0)
    {
        res=(res+ans)%mod;
        return ;
    }
    for(int i=min(d,s);i>=1;i--)
    {
        a[x]=i;c[i]++;
        int v=ans;
        v=v*inv[i]%mod*inv[c[i]]%mod*po[i/2]%mod;
        for(int j=1;j<x;j++)v=v*po[gd[i][a[j]]]%mod;
        dfs(x+1,i,s-i,v);
        c[i]--;
    }
}
int main()
{
    scanf("%d",&n);
    init();
    dfs(1,n,n,1);
    printf("%d\n",res);
    return 0;
}

EX Problem:

求有多少本质不同的不超过 n 个点的、无重边、可以有自环、存在至少一条欧拉回路的带
标号无向图。

首先带标号的点度均为偶数的无向图数量是\(2^{C_{n-1}^2}\),因为将一个点与剩下的n-2个点连边后,最后一个点的连边情况就确定了,所以每个点对答案的贡献都会除以2(相对不要求点度的无向图来说)

我们一样像上面一样讨论,只是最后求不动点个数的时候要保证所有点的度数均为偶数,这个连边的时候讨论一下奇偶性就可以了,注意可以连自环。

然后我们可以得到\(f_i\)表示i个点的度为偶的无向图个数,我们还要保证连通,设\(g_i\)为保证连通的图的个数,那么有:

\[g_n=f_n-\sum_{s_1\leq s_2...\leq s_m,s_1+s_2...+s_m=n,m\geq 2}\prod_{i=1}^n \overline{C}_{g_i}^{d_i} \]

其中\(d_i=\sum_{j=1}^{m}[s_j=i]\)\(\overline{C}_n^m\)为可重组合数。

posted @ 2020-01-20 14:26  lyyi2003  阅读(479)  评论(0编辑  收藏  举报