View on GitHub

Wenchong Huang

旧博客,文章搬迁完后删除

【BZOJ4894】天赋 题解

一句话题意:给定一个有向图,求外向生成树个数

直接使用矩阵树定理即可。需要注意的是,矩阵树定理要删除根所在的那行那列,这一点在无向图生成树计数时并没有特别说明,因为它对无向图不构成影响,但对有向图影响很大

#include<bits/stdc++.h>
#define ha 1000000007
using namespace std;

int Pow(int a,int b)
{
	int ans=1;
	for(;b;b>>=1,a=1ll*a*a%ha)
		if(b&1) ans=1ll*ans*a%ha;
	return ans;
}

int Det(int A[310][310],int n)
{
	int ans=1;
	for(int i=2;i<=n;i++)
	{
		int pos=i;
		while(pos<=n&&!A[pos][i]) pos++;
		if(!A[pos][i]) return 0;
		if(pos!=i)
		{
			ans=-ans;
			for(int j=2;j<=n;j++)
				swap(A[i][j],A[pos][j]);
		}
		ans=1ll*ans*A[i][i]%ha;
		int inv=Pow(A[i][i],ha-2);
		for(int j=i+1;j<=n;j++)
		{
			int t=1ll*A[j][i]*inv%ha;
			for(int k=2;k<=n;k++)
				A[j][k]=(A[j][k]-1ll*A[i][k]*t%ha+ha)%ha;
		}
	}
	return (ans+ha)%ha;
}

int G[310][310];

int main()
{
	int n;
	static char s[310];
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=n;j++)
			if(s[j]=='1') G[i][j]--,G[j][j]++;
	}
	printf("%d\n",Det(G,n));
	return 0;
}