专题做完了还是要说两句留下什么东西的。

矩阵树定理通俗点讲就是:

建立矩阵A[i][j]=-edge(i,j),(i!=j)。即矩阵这一项的系数是两点间直接相连的边数。

而A[i][i]=deg(i)。即对角线上都是这个点的度数。

得到这个矩阵后,随便删掉一行一列后进行高斯消元得到上三角矩阵,对角线上值的积就是生成树的个数。(就是行列式)

顺便提一下行列式的性质:

交换两行/列,行列式的值变为相反数。

一行的每一项减去另一行的若干倍,行列式不变。

一行的每一项都乘一个常数,行列式也乘这个常数。

到这里就够做题了。

 

T1:小Z的房间:

Descpiption:

你突然有了一个大房子,房子里面有一些房间。事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子。在一开始的时候,相邻的格子之间都有墙隔着。(n,m<=10)

你想要打通一些相邻房间的墙,使得所有房间能够互相到达。在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙)。同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路。现在,你希望统计一共有多少种可行的方案。Mod 10^9

板子。

 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 }
View Code

相关文章:

  • 2021-08-20
  • 2022-12-23
  • 2022-12-23
  • 2021-04-20
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-25
猜你喜欢
  • 2021-09-07
  • 2021-05-01
  • 2021-09-14
  • 2022-12-23
  • 2022-03-09
  • 2022-12-23
相关资源
相似解决方案