矩阵生成树

对于每条连边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


\operatorname{ec}(G) = t_w(G) \prod_{v\in V} \bigl(\deg(v)-1\bigr)!.

将结果乘上根节点出度即可

#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);
  }

 

posted @ 2017-01-06 14:43  z1j1n1  阅读(349)  评论(0编辑  收藏  举报