[WC2019] 数树
题目传送门
分析
最近老是在肝一些神仙生成函数题。。。哎,肝败吓疯。其实luogu题解里面的那篇已经很详细了,这篇题解纯属个人整理,建议是到到luogu题解去看。
题目大意:告诉你有俩棵有标号无根树,如果某两个节点共用了某条边,那么这两个点的权值必须相同,点权范围在 [ 1 , y ] [1,y] [1,y]内,有三个任务,求在给定2,1,0棵树的情况下构造树和点权的方案数。
Task0:简单转化
如果两棵树都给的话,就是把都存在的边放在图中,假设有 c n t cnt cnt个连通块,答案就是 y c n t y^{cnt} ycnt,因为是树,所以答案就是 y n − m y^{n-m} yn−m,其中 m m m是边数。
Task1:各种套路
现在少了一棵树,这个时候我们就要考虑怎么形式化问题。
不难发现,由于答案只和重合的边条数有关系,所以最简单的想法是枚举重合的边集。
A n s = ∑ S F ( S ) y n − ∣ S ∣ Ans=\sum\limits_SF(S)y^{n-|S|} Ans=S∑F(S)yn−∣S∣
其中 F ( S ) F(S) F(S)表示与初始树重合边集恰好为 S S S的方案数。
看到我加粗了恰好两个字就知道我要干什么了对吗:-)
套路1:容斥原理
设 C ( T ) C(T) C(T)表示重合的边集包含 T T T的方案数。
根据容斥原理,可以得到:
F ( S ) = ∑ S ⊆ T ( − 1 ) ∣ T ∣ − ∣ S ∣ C ( T ) F(S)=\sum\limits_{S\subseteq T} (-1)^{|T|-|S|}C(T) F(S)=S⊆T∑(−1)∣T∣−∣S∣C(T)
套路2:交换求和
这个时候带回原式化简一波
A n s = ∑ S F ( S ) y n − ∣ T ∣ = ∑ S ∑ S ⊆ T ( − 1 ) ∣ T ∣ − ∣ S ∣ C ( T ) y n − ∣ S ∣ = y n ∑ T ( − 1 ) ∣ T ∣ C ( T ) ∑ S ⊆ T ( − y ) − ∣ S ∣ Ans=\sum\limits_SF(S)y^{n-|T|}=\sum\limits_S\sum\limits_{S\subseteq T} (-1)^{|T|-|S|}C(T)y^{n-|S|}=y^n\sum\limits_T(-1)^{|T|}C(T)\sum\limits_{S\subseteq T} (-y)^{-|S|} Ans=S∑F(S)yn−∣T∣=S∑S⊆T∑(−1)∣T∣−∣S∣C(T)yn−∣S∣=ynT∑(−1)∣T∣C(T)S⊆T∑(−y)−∣S∣
发现后面那坨仅仅和集合大小有关系,我们枚举 T T T子集的大小 i i i,那么答案就是
A n s = y n ∑ T ( − 1 ) ∣ T ∣ C ( T ) ∑ i C ∣ T ∣ i ( − y ) i = y n ∑ T ( − 1 ) ∣ T ∣ C ( T ) ( 1 − 1 y ) ∣ T ∣ Ans=y^n\sum\limits_T(-1)^{|T|}C(T)\sum_i C_{|T|}^i(-y)^i=y^n\sum\limits_T(-1)^{|T|}C(T)(1-\frac{1}{y})^{|T|} Ans=ynT∑(−1)∣T∣C(T)∑iC∣T∣i(−y)i=ynT∑(−1)∣T∣C(T)(1−y1)∣T∣
于是我们得到了重要结论:
A n s = y n ∑ T C ( T ) ( 1 y − 1 ) ∣ T ∣ Ans=y^n\sum\limits_TC(T)(\frac{1}{y}-1)^{|T|} Ans=ynT∑C(T)(y1−1)∣T∣
然而到目前为止,复杂度仍然是指数级的,瓶颈在于 C ( T ) C(T) C(T),因此我们要继续形式化 C ( T ) C(T) C(T)。
套路3:矩阵树定理
考虑如果我把 T T T给你,要怎么求 C ( T ) C(T) C(T)。
考虑模型化问题,实际上就是钦定了若干条边,要求任意连边求生成树个数。
T T T中的一个连通块,显然不能再连边,因此将他们缩成一个点,任意两个连通块实际上有连通块大小乘积种连边方案。所以假设 T T T中的联通块大小分别为 a 1 , a 2 ⋯ a k a_1,a_2\cdots a_k a1,a2⋯ak,对于任意两个连通块 i , j i,j i,j,我们连 a i a j a_ia_j aiaj条边,形成的图的生成树个数就是 C ( T ) C(T) C(T)。
但是我们还是无法避免枚举 C ( T ) C(T) C(T),所以我们还得继续挖掘 C ( T ) C(T) C(T)的性质。索性,将 K i r c h h o f f Kirchhoff Kirchhoff矩阵拿出来玩玩。
[ a 1 ( n − a 1 ) − a 1 a 2 ⋯ − a 1 a k − a 1 a 2 a 2 ( n − a 2 ) ⋯ − a 2 a k ⋮ ⋮ ⋱ ⋯ − a k a 1 − a k a 2 ⋯ a k ( n − a k ) ] \left[ \begin{matrix} a_1(n-a_1) & -a_1a_2 & \cdots & -a_1a_k \\ -a_1a_2 & a_2(n-a_2) & \cdots & -a_2a_k \\ \vdots & \vdots & \ddots &\cdots \\ -a_ka_1 & -a_ka_2 &\cdots & a_k(n-a_k) \end{matrix} \right] ⎣⎢⎢⎢⎡a1(n−a1)−a1a2⋮−aka1−a1a2a2(n−a2)⋮−aka2⋯⋯⋱⋯−a1ak−a2ak⋯ak(n