天天看點

[HEOI2015] 小Z的房間

題目連結:戳我

其實是矩陣樹定理模闆題。

但是要注意不合法的情況預處理的時候設定成0,要不然計算行列式的時候有問題。直接跳過不合法情況,不給它建立新點就行了。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000000
using namespace std;
int n,m,cnt;
long long ans=1;
char cur[20][20];
int d[110][110],a[110][110],c[110][110],trans[20][20];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));
    memset(d,0,sizeof(d));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>cur[i][j];
            if(cur[i][j]=='.') trans[i][j]=++cnt;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(cur[i][j]=='.')
            {
                if(i+1<=n&&cur[i+1][j]=='.') a[trans[i][j]][trans[i+1][j]]=1,d[trans[i][j]][trans[i][j]]++;
                if(i-1>=1&&cur[i-1][j]=='.') a[trans[i][j]][trans[i-1][j]]=1,d[trans[i][j]][trans[i][j]]++;
                if(j+1<=m&&cur[i][j+1]=='.') a[trans[i][j]][trans[i][j+1]]=1,d[trans[i][j]][trans[i][j]]++;
                if(j-1>=1&&cur[i][j-1]=='.') a[trans[i][j]][trans[i][j-1]]=1,d[trans[i][j]][trans[i][j]]++;
            }
    n=cnt;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            c[i][j]=d[i][j]-a[i][j];
    for(int i=2;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            while(c[j][i])
            {
                int p=c[i][i]/c[j][i];
                for(int k=i;k<=n;k++)
                    c[i][k]=(c[i][k]-1ll*p*c[j][k]%mod+mod)%mod,swap(c[i][k],c[j][k]);          
                ans=-ans;
            }
    for(int i=2;i<=n;i++)
        ans=1ll*ans*c[i][i]%mod;
    printf("%lld\n",(ans+mod)%mod);
    return 0;
}                

轉載于:https://www.cnblogs.com/fengxunling/p/10261352.html