bzoj3659 Which Dreamed It BEST定理(公式绝对没错doge)

BEST定理

e c ( G ) = t w ( G ) ∏ u ∈ V ( d e g ( u ) − 1 ) ! ec(G)=t_w(G)\prod_{u \in V} (deg(u)-1)! ec(G)=tw(G)uV(deg(u)1)!

这(公式)要是有错我直播跳楼!倒挂跳楼!           ——Remmina

e c ( G ) ec(G) ec(G)指的是有向图 G G G中的欧拉回路个数,一个欧拉回路是一个环,从不同起点开始走这个环并不算不同的方案。

t w ( G ) t_w(G) tw(G)指的是以 w w w为根的外向生成树形图个数,可以用矩阵树定理计算。

d e g ( u ) deg(u) deg(u)指的是点 u u u的度数(入度或出度。在一张有欧拉回路的图中,所有点入度等于出度)

w w w随便一个点都可。

解题思路

裸上BEST定理后,由于本题题意中,从1号点出发走的第一条路不同,方案也不同,所以方案数要乘以 d e g ( 1 ) deg(1) deg(1)

代码

#include
using namespace std;
#define RI register int
int read() {
	int q=0;char ch=' ';
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
	return q;
}
const int mod=1000003;
int n,ans,a[105][105],rd[105],cd[105],fac[200005];

int qm(int x) {return x>=mod?x-mod:x;}
int guass() {
	int re=1;
	for(RI i=2;i<=n;++i) {
		for(RI j=i+1;j<=n;++j)
			while(a[j][i]) {
				int tmp=a[i][i]/a[j][i];
				for(RI k=i;k<=n;++k)
					a[i][k]=qm(a[i][k]-1LL*tmp*a[j][k]%mod+mod);
				swap(a[i],a[j]),re=qm(mod-re);
			}
		re=1LL*re*a[i][i]%mod;
	}
	return re;
}
int main()
{
	fac[0]=1;for(RI i=1;i<=200000;++i) fac[i]=1LL*fac[i-1]*i%mod;
    while(~scanf("%d",&n)&&n) {
    	for(RI i=1;i<=n;++i)
    		for(RI j=1;j<=n;++j) a[i][j]=0;
    	for(RI i=1;i<=n;++i) rd[i]=0;
    	for(RI i=1;i<=n;++i) {
    		cd[i]=read();int x;
    		for(RI j=1;j<=cd[i];++j)
    			x=read(),a[i][x]=qm(a[i][x]-1+mod),a[x][x]=qm(a[x][x]+1),++rd[x];
    	}
    	for(RI i=1;i<=n;++i) if(rd[i]!=cd[i]) {puts("0");continue;}
    	if(n==1) {printf("%d\n",fac[cd[1]]);continue;}
    	ans=1LL*guass()*cd[1]%mod;
    	for(RI i=1;i<=n;++i) ans=1LL*ans*fac[cd[i]-1]%mod;
    	printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(图论)