【Matrix-tree定理】【BEST Theorem】hdu6064 RXD and numbers

题意:给你一张有向图,求从1出发,回到1的欧拉回路数量。

先特判掉欧拉回路不存在时的情况。

看这个吧:http://blog.csdn.net/yuanjunlai141/article/details/76691680。

这是求有向图(以某个点为根的)生成外向树的方法。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll MOD=998244353ll;
int n,a[405][405],chu[405],ru[405];
ll A[405][405],jc[200005];
int sum;
bool vis[405];
void dfs(int U){
	++sum;
	vis[U]=1;
	for(int i=1;i<=n;++i){
		if(a[U][i] && !vis[i]){
			dfs(i);
		}
	}
}
ll Quick_Pow(ll a,ll p){
	if(!p){
		return 1ll;
	}
	ll res=Quick_Pow(a,p>>1);
	res=res*res%MOD;
	if((p&1ll)==1ll){
		res=a%MOD*res%MOD;
	}
	return res;
}
ll guass_jordan()
{
	if(n==2){
		return A[2][2];
	}
	for(int i=2;i<=n;++i){
		for(int j=2;j<=n;++j){
			A[i-1][j-1]=A[i][j];
		}
	}
    ll res=1;
    for(int i=1;i<n;++i)
      {
        int pivot=i;
        for(int j=i+1;j<n;++j)
          if(A[j][i]){
          	pivot=j;
          	break;
          }
        swap(A[i],A[pivot]);
        if(i!=pivot){
        	res=res*(MOD-1ll)%MOD;
        }
        if(A[i][i]==0){
            return 0;
        }
        ll ni=Quick_Pow(A[i][i],MOD-2ll);
        for(int j=i+1;j<n;++j)
          A[i][j]=A[i][j]*ni%MOD;
        res=res*A[i][i]%MOD;
        for(int j=1;j<n;++j)
          if(i!=j)
            for(int k=i+1;k<n;++k)
              A[j][k]=(A[j][k]-A[j][i]*A[i][k]%MOD+MOD)%MOD;
      }
    return res;
}
int main(){
//	freopen("hdu6064.in","r",stdin);
	jc[0]=1;
	for(int i=1;i<=200000;++i){
		jc[i]=jc[i-1]*(ll)i%MOD;
	}
	int zu=0;
	while(scanf("%d",&n)!=EOF){
		++zu;
		printf("Case #%d: ",zu);
		if(n==1){
			puts("1");
			continue;
		}
		memset(A,0,sizeof(A));
		memset(chu,0,sizeof(chu));
		memset(ru,0,sizeof(ru));
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				scanf("%d",&a[i][j]);
			}
		}
		bool flag=1;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				ru[i]+=a[j][i];
				chu[i]+=a[i][j];
				if(j!=i){
					A[i][i]=(A[i][i]+(ll)a[j][i])%MOD;
					if(a[i][j]){
						A[i][j]=MOD-a[i][j];
					}
				}
			}
			if(ru[i]!=chu[i]){
				flag=0;
				break;
			}
		}
		if(!flag){
			puts("0");
			continue;
		}
		sum=0;
		memset(vis,0,sizeof(vis));
		dfs(1);
		if(sum!=n){
			puts("0");
			continue;
		}
		ll ans=guass_jordan()*jc[ru[1]]%MOD;
		for(int i=2;i<=n;++i){
			ans=ans*jc[(ru[i]-1)]%MOD;
		}
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				ans=ans*Quick_Pow(jc[a[i][j]],MOD-2ll)%MOD;
			}
		}
		printf("%lld
",ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/7630380.html