矩阵树定理
大意
来自Luogu zhy137036的解释
行列式计算方法:
转换成上三角行列式
其中:交换两行答案乘上-1,行乘多少答案也要乘上(行列式是整数),行可以乘上一个数加到另一行上
for(int i=1;i<=cnt;i++) {
for(int j=i+1;j<=cnt;j++) {
while(a[j][i]) {
int t=a[i][i]/a[j][i];
for(int k=i;k<=cnt;k++) {
a[i][k]=((ll)a[i][k]-(ll)t*a[j][k])%p;
}
for(int k=i;k<=cnt;k++) {
swap(a[i][k],a[j][k]);
}
ans=-ans;
}
}
}
扩展
例题1
直接计算
WA了一次:int函数忘记返回值了
#include<bits/stdc++.h>
#define ll long long
const int p=1e9;
using namespace std;
const int N=105;
int n,m,id[N][N],a[N][N];
char s[N][N];
inline void add(int u,int v) {
a[u][v]--,a[u][u]++,a[v][v]++,a[v][u]--;
}
int main() {
scanf("%d%d",&n,&m); int cnt=0;
memset(id,0,sizeof(id));
for(int i=1;i<=n;i++) {
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++) {
if(s[i][j]=='.') {
id[i][j]=++cnt;
if(i>1&&id[i-1][j]) {
add(id[i-1][j],cnt);
}
if(j>1&&id[i][j-1]) {
add(id[i][j-1],cnt);
}
}
}
}
cnt--; int ans=1;
for(int i=1;i<=cnt;i++) {
for(int j=i+1;j<=cnt;j++) {
while(a[j][i]) {
int t=a[i][i]/a[j][i];
for(int k=i;k<=cnt;k++) {
a[i][k]=((ll)a[i][k]-(ll)t*a[j][k])%p;
}
for(int k=i;k<=cnt;k++) {
swap(a[i][k],a[j][k]);
}
ans=-ans;
}
}
}
for(int i=1;i<=cnt;i++) {
ans=(ll)ans*a[i][i]%p;
}
printf("%d\n",(ans+p)%p);
return 0;
}