【bzoj4031】 HEOI2015小Z的房间 矩阵树定理

第一次做矩阵树定理的题,其实就是记了个结论也没太看证明,然后学了学怎么用高斯消元求行列式,整数消元还真别扭,要用辗转相除,然后要注意取模的问题,一开始以为hzwer写麻烦了,后来想了想不加外面那句话会有问题,因为取模了。


#include
#include
#include
#include
#include
#include
#define mod 1000000000

using namespace std;

int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
long long a[110][110];
int n,m,id;
int vis[110][110];
char s[110];

long long det(int n)
{
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=n;j++)
	    a[i][j]=(a[i][j]+mod)%mod;
	long long ans=1,f=1;
	for (int i=1;i<=n;i++)
	{
		for (int j=i+1;j<=n;j++)
		{
			long long A=a[i][i],B=a[j][i];
		  	while (B)
		  	{
		  		long long t=A/B;A%=B;swap(A,B);
		  		for (int k=i;k<=n;k++)
		  	  		a[i][k]=(a[i][k]-t*a[j][k]%mod+mod)%mod;
		  		for (int k=i;k<=n;k++) swap(a[i][k],a[j][k]);
		  		f=-f;
		  	}
		}
		if (!a[i][i]) return 0;
		ans=ans*a[i][i]%mod;
	}
	if (f==-1) ans=(mod-ans)%mod;
	return ans;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for (int j=1;j<=m;j++)
		  if (s[j]=='.') vis[i][j]=++id;
	}
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++)
	    if (vis[i][j])
	      for (int k=0;k<4;k++)
	      {
	      	int x=i+dx[k],y=j+dy[k];
	      	if (x<=0 || y<=0 || x>n || y>m || !vis[x][y]) continue;
			a[vis[i][j]][vis[i][j]]++;a[vis[i][j]][vis[x][y]]--; 
	      }
	printf("%lld\n",det(id-1));
	return 0;
}


你可能感兴趣的:(线性代数,图论)