洛谷P4111,[HEOI2015]小Z的房间,Matrix-Tree图造树

正题

      这题就是套路题,一个无向图,计算构造一棵树的方案数, 很明显想到用Matrix-Tree定理来求解。

      我们构造一个n阶的矩阵,对于G[i][j],当i=j的时候,G[i][i]存的是i点的度数,当i!= j 时,记录的是i到j是否有边,有边即为-1,否则为0.

      然后删掉第i行和第i列,形成一个余子阵,求其行列式即可。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

int n,m;
int fact[15][15];
char s[15][15];
int tot=0;
long long d[110][110];
const long long Mod=1e9;

int main(){
	scanf("%d %d",&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]=='.') fact[i][j]=++tot;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(s[i][j]=='*') continue;
			int now=fact[i][j];
			int next;
			if(s[i][j+1]=='.'){
				next=fact[i][j+1];
				d[now][now]++;d[next][next]++;
				d[now][next]--;d[next][now]--;
			}
			if(s[i+1][j]=='.'){
				next=fact[i+1][j];
				d[now][now]++;d[next][next]++;
				d[now][next]--;d[next][now]--;
			}
		}
	tot--;
	long long ans=1;
	for(int i=1;i<=tot;i++)
		for(int j=1;j<=tot;j++)
			d[i][j]=(d[i][j]%Mod+Mod)%Mod;
	for(int j=1;j<=tot;j++){
		for(int i=j+1;i<=tot;i++)
			while(d[i][j]){
				long long temp=d[j][j]/d[i][j];
				for(int k=j;k<=tot;k++)
					d[j][k]=(d[j][k]-temp*d[i][k]%Mod+Mod)%Mod,swap(d[j][k],d[i][k]);
				ans*=-1;
			}
		ans*=d[j][j];
		ans=ans%Mod;
	}
	printf("%lld",(ans+Mod)%Mod);
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/81668395