矩阵生成树
对于每条连边i->j,a[i][j]--,a[i]++
对无向图有向图同时成立
求矩阵det即可
--------------------
BZOJ3659
wikipeida:
We denote these in- and out-degree of a vertex v by deg(v).
The BEST theorem states that the number ec(G) of Eulerian circuits in a connected Eulerian graph G is given by the formula
将结果乘上根节点出度即可
#include <cstdio> #define LL long long const LL mo=1000003; LL a[101][101],fac[200001],num[101]; LL qpow(LL bas,int powe){ LL ret=1; for (;powe;bas*=bas,bas%=mo){ if (powe&1) ret*=bas,ret%=mo; powe=powe>>1; } return(ret); } LL work(int n){ for (int i=1;i<=n;i++){ for (int j=i+1;j<=n;j++){ LL bas=a[j][i]*qpow(a[i][i],mo-2)%mo; for (int k=i;k<=n;k++) a[j][k]-=a[i][k]*bas%mo,a[j][k]%=mo,a[j][k]+=mo,a[j][k]%=mo; } } LL ret=1; for (int i=1;i<n;i++) ret*=a[i][i],ret%=mo; return(ret); } int main(){ fac[0]=1; for (int i=1;i<=200000;i++) fac[i]=fac[i-1]*i%mo; int n; while (scanf("%d",&n)!=EOF,n!=0){ for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=0; for (int i=1;i<=n;i++){ scanf("%d",&num[i]); for (int j=1;j<=num[i];j++){ int tt; scanf("%d",&tt); a[i][tt]--;a[i][i]++; } } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]%=mo,a[i][j]+=mo,a[i][j]%=mo; LL ans=1; for (int i=1;i<=n;i++) ans*=fac[num[i]-1],ans%=mo; ans*=work(n);ans%=mo; ans*=num[1];ans%=mo; printf("%lld\n",ans); } }
________________________________
BZOJ4031 求任意模数矩阵det
#include <cstdio> #define LL long long int cnt; const LL p=1e9; int n,m,id[101][101]; char st[101]; LL ans,a[101][101]; int ok(int x,int y){ return(x&&y&&x<=n&&y<=m&&id[x][y]); } void solve(LL a[],LL b[],int po){ while (a[po]!=0&&b[po]!=0){ if (a[po]<b[po]){ for (int i=po;i<=cnt;i++){ LL t=a[i];a[i]=b[i];b[i]=t; } ans*=-1; } LL bas=a[po]/b[po]; for (int i=po;i<=cnt;i++){ a[i]-=b[i]*bas; a[i]%=p;a[i]+=p;a[i]%=p; } } if (a[po]==0){ for (int i=po;i<=cnt;i++){ LL t=a[i];a[i]=b[i];b[i]=t; } ans*=-1; } } void work(){ for (int i=1;i<=cnt;i++) for (int j=i+1;j<cnt;j++) solve(a[i],a[j],i); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++){ scanf("%s",&st); for (int j=1;j<=m;j++) if (st[j-1]=='.') id[i][j]=++cnt; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (id[i][j]){ if (ok(i+1,j)) {int t1=id[i][j],t2=id[i+1][j];a[t1][t1]++;a[t2][t2]++;a[t1][t2]--;a[t2][t1]--;} if (ok(i,j+1)) {int t1=id[i][j],t2=id[i][j+1];a[t1][t1]++;a[t2][t2]++;a[t1][t2]--;a[t2][t1]--;} } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]%=p,a[i][j]+=p,a[i][j]%=p; ans=1; work(); for (int i=1;i<cnt;i++) ans*=a[i][i],ans%=p; printf("%lld\n",(ans%p+p)%p); }