专题做完了还是要说两句留下什么东西的。
矩阵树定理通俗点讲就是:
建立矩阵A[i][j]=-edge(i,j),(i!=j)。即矩阵这一项的系数是两点间直接相连的边数。
而A[i][i]=deg(i)。即对角线上都是这个点的度数。
得到这个矩阵后,随便删掉一行一列后进行高斯消元得到上三角矩阵,对角线上值的积就是生成树的个数。(就是行列式)
顺便提一下行列式的性质:
交换两行/列,行列式的值变为相反数。
一行的每一项减去另一行的若干倍,行列式不变。
一行的每一项都乘一个常数,行列式也乘这个常数。
到这里就够做题了。
T1:小Z的房间:
Descpiption:
板子。
1 #include<cstdio> 2 #include<algorithm> 3 #define mod 1000000000 4 int ord[11][11],n,m,tim,A[101][101];char s[11][11]; 5 void link(int a,int b){A[a][a]++;A[b][b]++;A[a][b]--;A[b][a]--;} 6 int Gauss(int ans=1){ 7 for(int i=1;i<=tim;++i)for(int j=i+1;j<=tim;++j)while(A[j][i]){ 8 int d=A[i][i]/A[j][i];for(int k=i;k<=tim;++k)A[i][k]=(A[i][k]-1ll*d*A[j][k]%mod+mod)%mod; 9 std::swap(A[i],A[j]);ans*=-1; 10 }for(int i=1;i<=tim;++i)ans=1ll*ans*A[i][i]%mod;return (ans+mod)%mod; 11 } 12 int main(){ 13 scanf("%d%d",&n,&m); 14 for(int i=1;i<=n;++i)scanf("%s",s[i]+1); 15 for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(s[i][j]=='.')ord[i][j]=++tim; 16 for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(s[i][j]=='.'){ 17 if(s[i-1][j]=='.')link(ord[i-1][j],ord[i][j]); 18 if(s[i][j-1]=='.')link(ord[i][j-1],ord[i][j]); 19 } 20 tim--;printf("%d\n",Gauss()); 21 }