【BZOJ 4031】: [HEOI2015]小Z的房间

时间:2024-06-12 19:04:14

题目大意:

  给一个n×m的网格,“.”表示可联通,求该网格可构成的生成树个数在1E9的剩余系中的结果。(n,m<=9)

题解:

  忘了删注释WA了两遍……

  直接建图+MartrixTree定理即可。

代码:

  

 #include "bits/stdc++.h"

 using namespace std;

 typedef long long ll;

 const int N=;

 ll a[N][N];

 int n,mod=1e9;

 inline ll det(){
ll res=;
for(int i=;i<n;++i){
if(!a[i][i]){
bool flag=false;
for(int j=i+;j<n;++j){
if(a[j][i]){
flag=true;
for(int k=i;k<n;++k) swap(a[i][k],a[j][k]);
res=-res;
break;
}
}
if(!flag) return ;
}
for(int j=i+;j<n;++j){
while(a[j][i]){
ll t=a[i][i]/a[j][i];
for(int k=i;k<n;++k){
a[i][k]=(a[i][k]-t*a[j][k])%mod;
swap(a[i][k],a[j][k]);
}
res=-res;
}
}
res*=a[i][i];
res%=mod;
}
if(res<) res+=mod;
return res;
} int main(){
int r,c;
scanf("%d%d",&r,&c);
char mp[][];
int s[][],xx[]={,,-,},
yy[]={,-,,};
memset(s,-,sizeof(s));
for(int i=;i<=r;++i)
scanf("%s",mp[i]+);
for(int i=;i<=r;++i)
for(int j=;j<=c;++j) if(mp[i][j]=='.')
s[i][j]=n++;
for(int i=;i<=r;++i)
for(int j=;j<=c;++j) if(s[i][j]!=-)
for(int k=;k<;++k){
int x=i+xx[k],y=j+yy[k];
if(x>&&y>&&x<=r&&y<=c){
if(s[x][y]!=-){
x=s[x][y],y=s[i][j];
a[x][y]=-,a[y][x]=-;
++a[y][y];
} }
}
--n;
printf("%lld\n",det());
}