0.概述
主要用于生成树有关问题。
事先声明:默认大家都知道比内-柯西定理。这里不再给出证明。
1.经典版:无向图
怎么求生成树个数呢?
1.1.构造
考虑用 ( n − 1 ) × m (n-1)\times m (n−1)×m 的矩阵与 m × ( n − 1 ) m\times (n-1) m×(n−1) 的矩阵相乘。乘积(是一个矩阵哦)的行列式,根据 B i n e t − C a u c h y \tt Binet-Cauchy Binet−Cauchy 可知,是这两个矩阵各选 n − 1 n-1 n−1 列。其实后面的矩阵是选 n − 1 n-1 n−1 行。
那么,我们不妨 让每一列都代表一条边。选 n − 1 n-1 n−1 列就是选出 n − 1 n-1 n−1 条边。
我们需要一个矩阵,使得这 n − 1 n-1 n−1 条边形成环时,行列式为零,这样就不会统计进去。注意,我们扔掉了一个点,这是危险的,所以要小心。
当然,我们已经站在了巨人的肩膀上,前人已经帮我们构造好了。对于第
k
k
k 条边
⟨
u
,
v
⟩
\langle u,v\rangle
⟨u,v⟩ ,矩阵
B
u
,
k
=
1
,
B
v
,
k
=
−
1
B_{u,k}=1,\;B_{v,k}=-1
Bu,k=1,Bv,k=−1 。我们要做的就是检验一下。虽然不可能找到错误。
1.1.1.有环
假如某些边形成环,不妨只看这些边。点可以重新编号,因为交换两行只改变符号,如果是 0 0 0 就一直是 0 0 0 。边亦如此。那我们得到一个“带状矩阵”,形如:
1 0 0 0 -1
-1 1 0 0 0
0 -1 1 0 0
0 0 -1 1 0
0 0 0 -1 1
显然这几列加在一起是全 0 0 0 。更标准地说,将每一列都加到第一列上,得到全 0 0 0 的一列,所以行列式肯定为 0 0 0 。即使去掉其中一行(也就是扔掉了一个点)也如此。
其实看成向量就可以完美感性理解了。
1.1.2.无环
无环则为树。树可以任意定一个根,不妨就把根设置为删掉的那个点。剩下的点按照深度排序。边的顺序也改改,令第 i i i 条边恰为第 i i i 个点与其父节点的连边——根就称为 0 0 0 号节点。
那么 B B B 矩阵一定是上三角——对于任意一个点,其父节点的编号更小,因为我们是按照深度排序的。所以行列式就是对角线上的值,是 ± 1 \pm 1 ±1 。符号是不确定的,因为点的编号是改过的,你没法使得对角线上都是 1 1 1 而不是 − 1 -1 −1 。
好消息是, ( ± 1 ) 2 = 1 (\pm 1)^2=1 (±1)2=1 。我们正好是两个矩阵相乘。所以第二个矩阵就设置为 B B B 的转置就好啦!
1.2.回归
那么 B × B T B\times B^T B×BT 究竟是个啥?——其中 B T B^T BT 表示转置。
可以看成每条边是一个虚点。 u → k → v u\rightarrow k\rightarrow v u→k→v 则乘积为 − 1 -1 −1 ,而 u → k → u u\rightarrow k\rightarrow u u→k→u 为 1 1 1 ,所以结论是:
G i , i G_{i,i} Gi,i 为点 i i i 的度数,而 G i , j G_{i,j} Gi,j 为二者之间边的数量的相反数。
1.3.拓展:求生成树边的乘积
如果一个生成树的权值定义为每条边的权值的乘积,咋整?也就是求
∑ T ( ∏ i ∈ T w i ) \sum_{T}\left(\prod_{i\in T}w_i\right) T∑(i∈T∏wi)
其实很好搞,可以将一条边看做 w k w_k wk 条重边,其中 w k w_k wk 为权值。
因为选择这条边的本质是连接两个端点,而此时有 w k w_k wk 条边都能做到这一点,那么生成树个数就会乘 w k w_k wk 。
如果 w k w_k wk 不是一个整数,而是任意一个定义了 + , − +,- +,− 与 × \times × 的类型呢?其实也是一样的。构造矩阵 B ′ B' B′ ,对于第 k k k 条边 ⟨ u , v ⟩ \langle u,v\rangle ⟨u,v⟩ ,令 B u , k ′ = w k , B v , k ′ = − w k B'_{u,k}=w_k,\;B'_{v,k}=-w_k Bu,k′=wk,Bv,k′=−wk ,那么 B ′ × B T B'\times B^T B′×BT 的行列式显然就是答案。而这个乘积就是原来的基尔霍夫矩阵(经典的 B × B T B\times B^T B×BT 称为基尔霍夫矩阵)进行上述微调的结果。
1.4.拓展:求生成树边的和
我们现在要求
∑
T
∑
i
∈
T
w
i
\sum_{T}\sum_{i\in T}w_i
T∑i∈T∑wi
枚举一条边?糟糕。事实上前面我已给出铺垫。
(
w
k
x
+
1
)
(w_k x+1)
(wkx+1) 也可以看做权值。然后最后的结果就是一次项系数。可是怎么求行列式(用到了高斯消元)呢?多项式求逆。真恶心。
2.拓展:有向图
怎么求生成树个数呢?这里的生成树肯定是一个外向树 / / / 内向树。由于本质相同,这里只求外向树。
2.1.构造
原来的 B B B 蛮好用的,咱可以接着用它。它可以保证,将边视作无向边时,形成一棵树。
但是不能用 B T B^T BT 了。我们得检验一下是不是外向的。如果还用原来的思路——按照深度排序,那么每一条边都应该是从父节点指向子节点的。也就是有向边的结尾一定要落在对角线上。否则就需要行列式为 0 0 0 。那么有向边 ⟨ u , v ⟩ \langle u,v\rangle ⟨u,v⟩ 就应该只有 v v v 为 1 1 1 ,而 u u u 应当为 0 0 0 ,这样就只能让 v v v 落在对角线上。所以构造 C k , v = 1 C_{k,v}=1 Ck,v=1 即可。
话说 B B B 的行列式好像是 ± 1 \pm 1 ±1 ?所以我们要小心,我们要让 B B B 的行列式只能为 + 1 +1 +1 。方法就是 ⟨ u , v ⟩ \langle u,v\rangle ⟨u,v⟩ 强制要求 B u , k = − 1 B_{u,k}=-1 Bu,k=−1 而 B v , k = 1 B_{v,k}=1 Bv,k=1 。这样一来,对角线上就只能全部是 + 1 +1 +1 了。
此时删掉的点就不是 “不妨设” 了,而是必须为外向树的根。
2.2.回归
B × C B\times C B×C 是啥捏?直接给结论, G i , i G_{i,i} Gi,i 是点 i i i 的入度,而 G i , j G_{i,j} Gi,j 是 i i i 到 j j j 的有向边的数量的相反数。
3.深入:容斥原理
其实矩阵树定理还有另一种理解方式,那就是容斥。
首先从 “生成树有 n − 1 n-1 n−1 条边,每个点的邻边中有一条边是连向父节点的” 入手,每个点都随意选一条边,假定其为父边。然而这很可能形成环。没关系,我们对环容斥一下就行了!毕竟,只要不形成环,必然是树。
我们随便搞出一个环,比如 x 1 → x 2 → x 3 → ⋯ → x k → x 1 x_1\rightarrow x_2\rightarrow x_3\rightarrow\cdots\rightarrow x_k\rightarrow x_1 x1→x2→x3→⋯→xk→x1 吧。那么剩下的点就还是乱选父边。方案数很好算,容斥系数是 − 1 -1 −1 的环个数次方。这能不能体现到行列式里呢?
交换任意两个数字,逆序对数量的奇偶性必然变化。所以,欲求奇偶性,只需要求经过多少次交换可以变成有序的。在行列式中 “有序” 就是主对角线。上面提到的环,等价于第 x i x_i xi 行选择了第 x i + 1 x_{i+1} xi+1 列的元素。显然可以交换第 x 1 x_1 x1 行、第 x 2 x_2 x2 行,再交换第 x 1 x_1 x1 行、第 x 3 x_3 x3 行,一直到交换 x 1 x_1 x1 行、第 x k x_k xk 行,共 ( k − 1 ) (k-1) (k−1) 次变为有序。
( − 1 ) k − 1 (-1)^{k-1} (−1)k−1 好像不太对。但是,如果在矩阵里用边数的相反数呢?不就是 ( − 1 ) k − 1 × ( − 1 ) k = − 1 (-1)^{k-1}\times(-1)^k=-1 (−1)k−1×(−1)k=−1 了吗?有 r r r 个环,系数就是 ( − 1 ) r (-1)^r (−1)r ,一点问题都没有了!
整个过程不需要 “边是无向的” 这一条件。有向图中,去掉根,每个点都有一条出边,又不形成有向环,就必然是内向树了。或者说,无向图只是把边当成了两条有向边,因为容斥的就是有向环。