生成树计数

矩阵树(Matrix-Tree)定理

假设有无向图 G ( V , E ) G(V,E) G(V,E)
D D D G ( V , E ) G(V,E) G(V,E) 的度数矩阵, D i D_i Di 表示结点 i i i 的度数,显然这是一个对角矩阵
A A A G ( V , E ) G(V,E) G(V,E) 的邻接矩阵, A i , j A_{i,j} Ai,j 表示结点 i , j i,j i,j 间的边数

Laplace矩阵 L L L 表示为 K = D − A K=D-A K=DA

去掉 L L L 的任意一行一列吗,留下一个子矩阵

然后这个行列式的值就是在这个图中**生成树的数量 **

d e t ( L ) = ∑ P ( ( − 1 ) τ ( P ) × L 1 , p 1 × L 2 , p 2 × L 3 , p 3 × ⋯ × L N , p N ) det(L)=\sum P((−1)^{\tau(P)}\times L_{1,p1}\times L_{2,p2}\times L_{3,p3}\times ⋯\times L_{N,pN}) det(L)=P((1)τ(P)×L1,p1×L2,p2×L3,p3××LN,pN)

P P P 是一个排列, τ ( P ) \tau(P) τ(P) 是逆序对个数

矩阵行列式有一个性质:

如果把矩阵的某一行(列)加上另一行(列)的k倍,则行列式的值不变。

所以把矩阵消为一个上三角矩阵后,然后求出对角线的积,便是该矩阵的行列式的值。

BEST 定理

G G G 是有向欧拉图,那么 G G G 不同欧拉回路可以这么构造

指定一个点为根节点,取一颗根向树,然后给对于每一个节点,给他连出去的非树边编一个顺序,要求根节点的第一条边要编号最小。然后从根节点出发,按顺序走非树边,没有非树边就走树边。可以证明最后能走回根节点,且所有的边都遍历到了。

所以欧拉回路总数是 根向生成树的个数 × ∏ v ∈ V ( d e g v − 1 ) ! \text{根向生成树的个数}\times \prod_{v\in V} (deg_v-1)! 根向生成树的个数×vV(degv1)! d e g deg deg 是出度。

记不同欧拉回路总数为 e c ( G ) ec(G) ec(G)
e s ( G ) = t r o o t ( G , k ) × ∏ v ∈ V ( d e g v − 1 ) ! es(G)=t^{root}(G,k)\times \prod_{v\in V}(deg_v-1)! es(G)=troot(G,k)×vV(degv1)!

树(图)的计数的多项式算法

小朋友与二叉树

我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树。
考虑一个含有n个互异正整数的序列c[1],c[2],…,c[n]。如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{c[1],c[2],…,c[n]}中,我们的小朋友就会将其称作神犇的。并且他认为,一棵带点权的树的权值,是其所有顶点权值的总和。
给出一个整数m,你能对于任意的s(1<=s<=m)计算出权值为s的神犇二叉树的个数吗?请参照样例以更好的理解什么样的两棵二叉树会被视为不同的。
我们只需要知道答案关于998244353(7×17×2^23+1,一个质数)取模后的值。

G ( x ) = ∑ n ≥ 0 [ n ∈ C ] x n G(x)=\sum_{n\ge0}[n\in C]x^n G(x)=n0[nC]xn ,合法二叉树对应的生成函数为 F ( x ) F(x) F(x)

根据题意
F ( x ) = F 2 ( x ) G ( x ) + 1 G ( x ) F 2 ( x ) − F ( x ) + 1 = 0 F ( x ) = 1 ± 1 − 4 G ( x ) 2 G ( x ) F ( x ) = 2 1 ± 1 − 4 G ( x ) F(x)=F^2(x)G(x)+1 \\ G(x)F^2(x)-F(x)+1=0\\ F(x)=\frac{1\pm\sqrt{1-4G(x)}}{2G(x)}\\ F(x)=\frac{2}{1\pm\sqrt{1-4G(x)}}\\ F(x)=F2(x)G(x)+1G(x)F2(x)F(x)+1=0F(x)=2G(x)1±14G(x) F(x)=1±14G(x) 2
分母常数项不能为 0 0 0 ,所以
F ( x ) = 2 1 + 1 − 4 G ( x ) F(x)=\frac{2}{1+\sqrt{1-4G(x)}}\\ F(x)=1+14G(x) 2
调用多项式求逆和多项式开根计算即可,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

大朋友与多叉树

求满足如下条件的多叉树个数:
1.每一个点的儿子个数在给定的集合 S S S
2.总的叶子节点树为 s s s

儿子之间有顺序关系,但节点是没有标号的。

F ( x ) F(x) F(x) 是生成一颗含 i i i 个叶节点的合法树的个数的生成函数。

那么
F ( x ) = x + ∑ i ∈ S F i ( x ) F(x)=x+\sum_{i\in S} F^i(x) F(x)=x+iSFi(x)
G ( x ) = x − ∑ i ∈ S x i G(x)=x-\sum_{i\in S}x^i G(x)=xiSxi 。那么
G ( F ( x ) ) = x G(F(x))=x G(F(x))=x
使用拉格朗日反演求复合逆即可,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

YJC plays Minecraft

给出若干个完全图,然后完全图之间首尾相连并成环,要求删边使得两点之间路径数不超过 1 1 1 ,求方案数。

f n f_n fn 表示 n n n 个节点完全图的生成树个数, g n g_n gn 表示 n n n 个节点完全图的生成森林个数, h n h_n hn 表示 n n n 个节点完全图,点 1 1 1 和点 n n n 不在一棵树中的生成森林个数。 F ( x ) , G ( x ) , H ( x ) F(x),G(x),H(x) F(x),G(x),H(x) 是对应的生成函数。

答案就是 2 n ∏ i = 1 n g a i − ∏ i = 1 n ( g a i − h a i ) 2^n\prod_{i=1}^ng_{a_i}-\prod_{i=1}^n(g_{a_i}-h_{a_i}) 2ni=1ngaii=1n(gaihai)

已知 F ( x ) = ∑ i i − 2 i ! x i F(x)=\sum\frac{i^{i-2}}{i!}x^i F(x)=i!ii2xi G ( x ) = ∑ F i ( x ) x ! = e F ( x ) G(x)=\sum\frac{F^i(x)}{x!}=e^{F(x)} G(x)=x!Fi(x)=eF(x)

考虑 H ( x ) H(x) H(x) ,枚举 1 1 1 号节点所在块的大小可得 h n = ∑ i = 0 n − 2 f i + 1 g n − i − 1 ( n − 2 i ) h_n=\sum_{i=0}^{n-2}f_{i+1}g_{n-i-1}{n-2 \choose i} hn=i=0n2fi+1gni1(in2)

生成树形式为 H ′ ′ ( x ) = F ′ ( x ) G ′ ( x ) H''(x)=F'(x)G'(x) H(x)=F(x)G(x)

调用 N T T NTT NTT 即可。

仙人掌

(填坑

点双

(填坑

边双

(填坑

有向无环图

(填坑

强连通图

(填坑

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
最小生成树(Minimum Spanning Tree, MST) 是一种用于寻找连通图中的最小权重生成树的算法。可以使用Matlab中的minspantree()函数来求解最小生成树。首先,需要定义一个边权矩阵,其中每一列表示一条边,从上到下分别为两个顶点以及它们边的权值。然后,使用sortrows函数对边权矩阵的第三列进行排序,得到排序后的边权矩阵。接下来,使用循环遍历每条边,判断当前边连接的两个顶点是否在同一个集合中,如果不在同一个集合中,则将该边加入最小生成树中,并更新顶点集合的标记。最终,得到最小生成树的边集合和总长度。以下是用Matlab代码实现最小生成树的示例: ```matlab % 边权矩阵,每一列都表示一条边,从上到下分别为两个顶点以及它们边的权值 b = [1 1 1 2 2 3 3 4; 2 4 5 3 5 4 5 5; 8 1 5 6 7 9 10 3]; % 对边权矩阵按权值进行排序 [B, i = sortrows(b', 3); B = B'; % 边的条数和点的个数 m = size(b, 2); n = 5; % t数组用来标记选中的边,k用来计数,T矩阵用来存储选中的边,c计算最小生成树的总长度 t = 1:n; k = 0; T = []; c = 0; for i = 1:m if t(B(1, i)) ~= t(B(2, i)) k = k + 1; T(k, 1:2) = B(1:2, i); c = c + B(3, i); tmin = min(t(B(1, i)), t(B(2, i))); tmax = max(t(B(1, i)), t(B(2, i))); for j = 1:n if t(j) == tmax t(j) = tmin; end end end if k == n - 1 break; end end T % 输出最小生成树的边集合 c % 输出最小生成树的总长度 ``` 这段代码将输出最小生成树的边集合和总长度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [MATLAB 最小生成树](https://blog.csdn.net/qq_63585949/article/details/128908785)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [最小生成树matlab求解](https://blog.csdn.net/Planck_meteora/article/details/123342485)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【MATLAB】最小生成树Kruskal算法](https://blog.csdn.net/weixin_46308081/article/details/119202910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值