题解:
因为持续写题感到恶心又不想显得太颓于是随便存几个板子
求生成树方案数?
矩阵树定理板子题。
这就当我存个板子的地方吧。
总之就是对于边(i,j),矩阵a[i][j]值-1,a[i][i]值+1。然后求个行列式即可。
代码:
#include<cstdio>
#include<algorithm>
#define maxn 105
#define mod 1000000000
using namespace std;
int n,m,d[5]={0,1,0,-1,0},id[maxn][maxn],cnt,a[maxn][maxn];
char s[maxn][maxn];
int gauss()
{
int r,c,fl=0;
for(r=c=1;r<n&&c<m;r++,c++)
{
int maxr=r;
for(int i=r;i<n;i++)
if(a[i][c]) { maxr=i; break; }
if(!a[maxr][c]) return 0;
if(maxr!=r)
{
fl^=1;
for(int i=0;i<m;i++) swap(a[r][i],a[maxr][i]);
}
for(int i=r+1;i<n;i++)
while(a[i][c])
{
int delta=a[i][c]/a[r][c];
for(int j=c;j<m;j++) a[i][j]=(a[i][j]-1ll*delta*a[r][j]%mod)%mod;
if(!a[i][c]) break;
fl^=1;
for(int j=0;j<m;j++) swap(a[r][j],a[i][j]);
}
}
if(r!=n) return 0;
int res=1;
for(int i=1;i<n;i++) res=1ll*res*a[i][i]%mod;
if(fl) res=-res;
return (res+mod)%mod;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.') id[i][j]=cnt++;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')
for(int k=1;k<=4;k++)
{
int cx=i+d[k-1],cy=j+d[k];
if(s[cx][cy]=='.') a[id[i][j]][id[i][j]]++,a[id[i][j]][id[cx][cy]]=-1;
}
n=m=cnt;
printf("%d\n",gauss());
}