写在前面:在复健矩阵的时候发现了 [NOI2007]生成树计数
这个题,遂起兴研究生成树计数
个结点的环的生成树个数为
个结点的完全图的生成树个数为
第一句话很好理解,只要去除环中的任意一条边,就是一棵生成树
第二句话也叫
犹记两年前
Prufer Code
以下提到的树都是有标号无根树
每棵结点数大于
由树构造
- 找到叶子结点中编号最小的,记作
,将 的父结点 加入序列 - 删去
结点 - 重复步骤 1. 和 2. ,直到整棵树只剩下两个结点,结束
显然,若整棵树有
由构造过程,可以得出两个结论:
- 结点
最后一定没有被删除 - 每个结点的度是序列中该结点出现次数
根据构造过程,相似地,可以得出由
- 根据度数为
确定当前的叶子结点,找出叶子结点中编号最小的结点,记作 ,将 的父结点设为序列中第一个没有遍历过的结点 - 删去
, 度数 ,如果 度数为 ,那么把其加入叶子节点集合中 - 重复 1. 和 2. ,最后会剩下两个叶子结点,将其连接,结束
由每一步构造的唯一性以及每一步反构造的唯一性,由反证法可以得出
- 不存在两个
序列对应同一棵树 - 不存在两棵树对应同一个
序列
设
若要钦定根,最后可以添加一个根节点,序列长度变为
更好的构造与反构造方法
用代码模拟构造和反构造当然可以用小根堆,时间复杂度
还有一种更为快速的方法
构造:
- 找到编号最小的叶子结点
,父结点 加入序列 - 若删去
后, 变为叶子结点,且编号比 小,则 为当前编号最小的叶子结点,直接令 为 ,重复操作 1. 和 2. - 若不满足 2. ,将
自增,直到找到下一个未删除的叶子结点
1 | int p; |
反构造:同上
看代码
1 | int p; |
OK
学完
有根树对应
来点数学
如果给定
考虑
完全二分图生成树个数?
左部点
构造
以上
CF917D(这道题也是曾经
ARC106F(需要生成函数,不会捏)
牛客挑战赛48C(这个可以写)
TopCoder SRM697 div1 hard 是这道 (看不懂所以不写)
把一些参考放在这里
《Tree-structured Data Regeneration with Network Coding in Distributed Storage Systems》
【朝夕的ACM笔记】图论-Prufer序列 - 知乎 (zhihu.com)
Prufer 序列 - Achtoria - 博客园 (cnblogs.com)
作者: wsy_jim