【Luogu】 P4727 [HNOI2009] 图的同构计数

文章介绍了如何应用Burnside引理解决图论中的问题,特别是关于置换环和等价类的计算。它涉及将图拆分成置换环,计算环内和环间的等价类个数,并通过Burnside引理求解固定置换下的不动点个数。最后,给出了一个C++程序实现该算法。
摘要由CSDN通过智能技术生成

题目链接

点击打开链接

题目解法

可以参考这篇博客

看到同构、重新标号,首先想到置换然后用 b u r n s i d e burnside burnside 引理
考虑将边染色,出现在图中的为 1,未出现的为 0

考虑一个已经固定的置换的等价类个数
一、将图拆分成若干个置换环
一个 n n n 个点的置换必定可以拆分成若干个置换环,其大小分别为 b 1 , b 2 , . . . , b m b_1,b_2,...,b_m b1,b2,...,bm

二、计算环内的等价类个数
考虑将点旋转之后,长度相同的边必定在同一个等价类中(这里把边做置换,与上面把点置换不同),一个 n n n 个点的完全图中长度不同的边的个数共有 n 2 \frac{n}{2} 2n 条,所以环内的等价类个数为 ∑ ⌊ b i 2 ⌋ \sum \lfloor \frac{b_i}{2}\rfloor 2bi
这里可以借用一下这张图,来更好地理解(其中同种颜色的边属于同一个等价类):
在这里插入图片描述

三、计算环与环之间的等价类个数
先考虑大小为 4 , 6 4,6 4,6 的环,用前一个数表示环 1 中的点,后一个数表示环 2 中的点,那么 ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) , ( 4 , 4 ) , ( 1 , 5 ) , ( 2 , 6 ) , ( 3 , 1 ) , . . . (1,1),(2,2),(3,3),(4,4),(1,5),(2,6),(3,1),... (1,1),(2,2),(3,3),(4,4),(1,5),(2,6),(3,1),... 都属于同一个等价类,在这个例子中,等价类的个数为 2
对于大小分别为 s 1 , s 2 s_1,s_2 s1,s2 的两个环,其中每个等价类中有 [ s 1 , s 2 ] [s1,s2] [s1,s2] 个点,那么共有 s 1 ∗ s 2 [ s 1 , s 2 ] = ( s 1 , s 2 ) \frac{s1*s2}{[s1,s2]}=(s1,s2) [s1,s2]s1s2=(s1,s2) 个等价类

所以对于一个固定的置换,等价类的个数即为 ∑ i = 1 m ⌊ b i 2 ⌋ + ∑ i = 1 m ∑ j = 1 i − 1 ( b i , b j ) \sum_{i=1}^{m} \lfloor \frac{b_i}{2}\rfloor+\sum_{i=1}^{m}\sum_{j=1}^{i-1}(b_i,b_j) i=1m2bi+i=1mj=1i1(bi,bj)

计算对于每一个固定的 b 1 , . . . , b m b_1,...,b_m b1,...,bm 的方案数
b i b_i bi 出现了 c i c_i ci 次(下文的 c i c_i ci 认为是对不同的 b i b_i bi,即相同的 b i b_i bi 只计算一次 c i c_i ci
考虑总共有 n ! n! n! 种置换( 1 − n 1-n 1n 随意匹配)
考虑每个长度为 b b b 的循环会重复出现 b ! b! b! 次,因为点的顺序不影响 b b b 的大小
所以 1 − n 1-n 1n 分给 m m m 个循环的方案数为 n ! Π ( b i ! ) \frac{n!}{\Pi(b_i!)} Π(bi!)n!
考虑相同的 b b b 之间可能会有重复,例如 ( 1 , 2 ) ( 3 , 4 ) (1,2)(3,4) (1,2)(3,4) ( 3 , 4 ) ( 1 , 2 ) (3,4)(1,2) (3,4)(1,2) 是同一种方案,只不过顺序不同,所以方案数需除以 Π ( c i ! ) \Pi (c_i!) Π(ci!)
考虑置换内部可以重新排序,又因为置换是一个环,所以方案数需要乘 Π ( b i − 1 ) ! \Pi(b_i-1)! Π(bi1)!
所以最终的方案数为 n ! Π ( b i ! ) ∗ Π ( c i ! ) ∗ Π ( b i − 1 ) ! \frac{n!}{\Pi(b_i!)*\Pi (c_i!)}*\Pi(b_i-1)! Π(bi!)Π(ci!)n!Π(bi1)!,即为 n ! Π b i ∗ Π ( c i ! ) \frac{n!}{\Pi b_i*\Pi (c_i!)} ΠbiΠ(ci!)n!

根据 b u r n s i d e burnside burnside 引理,不动点个数即为 ∑ n ! Π b i ∗ Π ( c i ! ) ∗ 2 k \sum \frac{n!}{\Pi b_i*\Pi (c_i!)}*2^k ΠbiΠ(ci!)n!2k
其中 k = ∑ i = 1 m ⌊ b i 2 ⌋ + ∑ i = 1 m ∑ j = 1 i − 1 ( b i , b j ) k=\sum_{i=1}^{m} \lfloor \frac{b_i}{2}\rfloor+\sum_{i=1}^{m}\sum_{j=1}^{i-1}(b_i,b_j) k=i=1m2bi+i=1mj=1i1(bi,bj)
所以 A n s = 1 n ! ∗ ∑ n ! Π b i ∗ Π ( c i ! ) ∗ 2 k = ∑ 2 k Π b i ∗ Π ( c i ! ) Ans=\frac{1}{n!}*\sum \frac{n!}{\Pi b_i*\Pi (c_i!)}*2^k=\sum \frac{2^k}{\Pi b_i*\Pi (c_i!)} Ans=n!1ΠbiΠ(ci!)n!2k=ΠbiΠ(ci!)2k

因为只需要枚举不同的 b 1 , . . . , b m b_1,...,b_m b1,...,bm 所以时间是可以过的(具体我也分析不出来)

#include <bits/stdc++.h>
using namespace std;
const int N(70),P(997);
int n,ans,b[N],c[N];
int inv[N],facinv[N],bs2[2000];
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
void dfs(int dep,int las){
	if(!las){
		int k=0;
		for(int i=1;i<dep;i++){
			k+=b[i]/2;
			for(int j=1;j<i;j++) k+=__gcd(b[i],b[j]);
		}
		int res=bs2[k];
		for(int i=1;i<dep;i++) res=res*inv[b[i]]%P;
		for(int i=1;i<dep;i++) if(b[i]!=b[i-1]) res=res*facinv[c[b[i]]]%P;
		ans=(ans+res)%P;
		return;
	}
	for(int i=max(1,b[dep-1]);i<=las;i++){
		b[dep]=i,c[i]++;
		dfs(dep+1,las-i);
		c[i]--;
	}
}
int main(){
	n=read();
	inv[1]=1,facinv[1]=1;
	for(int i=2;i<N;i++) inv[i]=(P-P/i)*inv[P%i]%P,facinv[i]=facinv[i-1]*inv[i]%P;
	bs2[0]=1;
	for(int i=1;i<2000;i++) bs2[i]=bs2[i-1]*2%P;
	dfs(1,n);
	printf("%d",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值