【BZOJ1015】星球大战
【BZOJ1016】最小生成树计数

【BZOJ4031】小Z的房间

Zarxdy34 posted @ 2015年10月21日 16:17 in BZOJ with tags Matrix-Tree定理 , 556 阅读

  据说数据有非法字符,exited,成功爆了我的读入。

  Matrix-Tree定理,算行列式时消元用辗转相除法。

 

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
const int maxn=12,mo=1000000000;
inline char readchar() {char ch;while (!((ch=getchar())=='.' || ch=='*'));return ch;}

struct Matrix
{
	int a[maxn*maxn][maxn*maxn];
	int n;

	int* operator[] (int x) {return a[x];}

	int det()
	{
		int ans=1;
		for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=(a[i][j]%mo+mo)%mo;
		for (int i=1;i<n;i++)
		{
			for (int j=i+1;j<=n;j++) while (a[j][i])
			{
				int x=a[i][i]/a[j][i];
				for (int k=i;k<=n;k++) a[i][k]=(a[i][k]-1ll*x*a[j][k]%mo+mo)%mo;
				for (int k=i;k<=n;k++) swap(a[i][k],a[j][k]);
				ans=-ans;
			}
		}
		if (ans==-1) ans+=mo;
		for (int i=1;i<=n;i++) ans=1ll*ans*a[i][i]%mo;
		return ans;
	}
}M;

int id[maxn][maxn],ids;
int n,m;

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (readchar()=='.') id[i][j]=++ids;
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (id[i][j])
	{
		if (i>1 && id[i-1][j]) M[id[i][j]][id[i][j]]++,M[id[i][j]][id[i-1][j]]=-1;
		if (i<n && id[i+1][j]) M[id[i][j]][id[i][j]]++,M[id[i][j]][id[i+1][j]]=-1;
		if (j>1 && id[i][j-1]) M[id[i][j]][id[i][j]]++,M[id[i][j]][id[i][j-1]]=-1;
		if (j<m && id[i][j+1]) M[id[i][j]][id[i][j]]++,M[id[i][j]][id[i][j+1]]=-1;
	}
	M.n=ids-1;
	printf("%d\n",M.det());
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter