1. 程式人生 > >BZOJ 4031 小Z的房間 (矩陣樹定理)

BZOJ 4031 小Z的房間 (矩陣樹定理)

題意:

計算給定圖的生成樹的個數

分析:

矩陣樹定理板題。

#include<bits/stdc++.h>

using namespace std;

int z[11][11];
int a[90][90];
char s[11][11];

const int mod=1e9;

int n,m,S;

int gs(){
    S--;
    for(int i=1;i<=S;i++){
        for(int j=1;j<=S;j++){
            a[i][j]=(a[i][j]+mod)%mod;
        }
    }
    long long ans=1;
    for(int j=1;j<=S;j++){
        for(int i=j+1;i<=S;i++){
            while(a[i][j]){
                long long t=a[j][j]/a[i][j];
                for(int k=j;k<=S;k++){
                    a[j][k]=(a[j][k]-t*a[i][k]%mod+mod)%mod;
                    swap(a[i][k],a[j][k]);
                }
                ans*=-1;
            }
        }
        if(a[j][j]==0) return 0;
        ans=ans*a[j][j]%mod;
    }
    return (ans+mod)%mod;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
    }
    for(int i=0;i<=n+1;i++){
        for(int j=0;j<=m+1;j++){
            if(i==0||j==0||i==n+1||j==m+1){
                s[i][j]='*';
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s[i][j]=='.'){
                z[i][j]=++S;
                if(s[i-1][j]=='.'){
                    a[z[i-1][j]][z[i][j]]=1;
                    a[z[i][j]][z[i-1][j]]=1;
                }
                if(s[i][j-1]=='.'){
                    a[z[i][j-1]][z[i][j]]=1;
                    a[z[i][j]][z[i][j-1]]=1;
                }
            }
        }
    }
    for(int i=1;i<=S;i++){
        for(int j=1;j<=S;j++){
            if(a[i][j]&&i!=j){
                a[i][j]=-a[i][j];
                a[i][i]++;
            }
        }
    }
    printf("%d\n",gs());
    return 0;
}