BZOJ 4031: [HEOI2015]小Z的房间(Matrix Tree)

传送门

解题思路

  矩阵树定理模板题。矩阵树定理是求图中最小生成树个数,做法是首先求出基尔霍夫矩阵,就是度数矩阵(-)邻接矩阵。然后再求出这个矩阵的行列式,行列式的求法就是任意去掉一行一列,然后高斯消元消成上三角,对角线乘积即为行列式。注意到这里有取模,所以要辗转相除。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define int long long
typedef long long LL;

using namespace std;
const int MAXN = 11;
const int MAXM = MAXN*MAXN;
const int MOD = 1e9;

int n,m,tot,Mp[MAXN][MAXN],f[MAXM][MAXM],ans=1;
char s[MAXN][MAXN];

inline void add(int x,int y){
	f[x][x]++;f[y][y]++;f[x][y]--;f[y][x]--;
}

inline void Matrix_Tree(){
	int t;
	for(int i=1;i<tot;i++){
		for(int j=i+1;j<tot;j++)
			while(f[j][i]){
				t=f[i][i]/f[j][i];
				for(int k=i;k<tot;k++)
					f[i][k]=(f[i][k]-t*f[j][k]%MOD+MOD)%MOD;
				swap(f[i],f[j]);ans=-ans;
			}
		ans=ans*f[i][i]%MOD;
	}
	ans=(ans+MOD)%MOD;
}

signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++) {
		scanf("%s",s[i]+1);
		for(int j=1;j<=m;j++)
			if(s[i][j]=='.') Mp[i][j]=++tot;	
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) if(s[i][j]=='.'){
			if(Mp[i-1][j]) add(Mp[i][j],Mp[i-1][j]);
			if(Mp[i][j-1]) add(Mp[i][j],Mp[i][j-1]);
		}
	Matrix_Tree();printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/10044592.html