码迷,mamicode.com
首页 > 其他好文 > 详细

矩阵树定理

时间:2015-10-05 20:44:13      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:

bzoj4031 小z的房间

题目大意:给定n*m的网格,有一些障碍点,求生成树的个数。

思路:矩阵数定理直接求解就可以了。但是因为要取模所以要稍微修改一下高斯消元,行列式交换行或列的时候行列式的值要变号。

技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define p 1000000000
#define LL long long
#define maxm 105
using namespace std;
char map[maxm][maxm];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},bi[maxm][maxm]={0};
LL ai[maxm][maxm]={0};
char in(){
    char ch;
    while(scanf("%c",&ch)==1){
        if (ch==.||ch==*) return ch;
    }
}
int work(int n){
    int i,j;LL x,y,k,ans=1,f=1,t;
    for (i=1;i<=n;++i)
      for (j=1;j<=n;++j) ai[i][j]=(ai[i][j]+p)%p;
    for (i=1;i<=n;++i){
        for (j=i+1;j<=n;++j){
            x=ai[i][i];y=ai[j][i];
            while(y!=0){
                k=x/y;x%=y;swap(x,y);f=-f;
                for (t=i;t<=n;++t) 
                  ai[i][t]=(ai[i][t]-k*ai[j][t]%p+p)%p;
                for (t=i;t<=n;++t) swap(ai[i][t],ai[j][t]);
            }
        }if (!ai[i][i]) return 0;
        ans=ans*ai[i][i]%p;
    }return (int)(ans*f%p+p)%p;
}
int main(){
    int n,m,i,j,k,x,y,tot=0,u,v;scanf("%d%d",&n,&m);
    for (i=1;i<=n;++i){
        for (j=1;j<=m;++j){map[i][j]=in();if (map[i][j]==.) bi[i][j]=++tot;}
    }for (i=1;i<=n;++i)
      for (j=1;j<=m;++j){
          if (map[i][j]!=.) continue;
          for (k=0;k<4;++k){
              x=i+dx[k];y=j+dy[k];
              if (x<1||x>n||y<1||y>m||map[x][y]!=.) continue;
              u=bi[i][j];v=bi[x][y];
              ++ai[u][u];--ai[u][v];
          }
      }printf("%d\n",work(tot-1));
}
View Code

 

矩阵树定理

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4856173.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!