矩阵树定理

大意

来自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

Luogu P4111 [HEOI2015]小 Z 的房间

直接计算
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;
}
posted @ 2021-04-07 16:10  wwwsfff  阅读(72)  评论(0编辑  收藏  举报