Prüfer 序列
由于本人过菜,故写文备忘。
参考资料:
https://www.luogu.com.cn/blog/TheLostWeak/solution-p2290
https://oi-wiki.org/graph/prufer
https://github.com/cp-algorithms/cp-algorithms/blob/master/src/graph/pruefer_code.md
Prüfer 序列常用于组合计数问题上。
Prüfer 序列可以将一个带标号
从树到序列
每次选择一个编号最小的叶结点并删掉它,然后在序列中记录下它连接到的那个结点。重复
线性构造法
用指针
若
注意在这个过程中不改动 p,因为 p 可以在上述操作后仍保持原有 1 到 p-1 间不存在 0 度节点的性质。
若
循环执行直到未被删除的节点只剩 2 个,结束。
//此代码摘取自https://github.com/cp-algorithms/cp-algorithms/blob/master/src/graph/pruefer_code.md vector<int> code(n - 2); int leaf = ptr; for (int i = 0; i < n - 2; i++) { int next = parent[leaf]; code[i] = next; if (--degree[next] == 1 && next < ptr) { leaf = next; } else { ptr++; while (degree[ptr] != 1) ptr++; leaf = ptr; } }
复杂度分析:除了删除节点和
从序列到树
刚开始你有一个点集
循环执行以下操作:
拿出 Prüfer 序列最靠前的数,拿出点集中不在当前 Prüfer 序列中的编号最小的点。在两个点之间连一条边。
同样可以线性时间解决。
性质
- Prüfer 序列与无根树为双射关系。
- 度数为
的节点会在序列中出现 次。 - 节点
一定会活到最后。
例题
给定了每个节点的度数,那么该节点在 Prüfer 序列中出现次数也确定了。那么就是一个可重集合排列。
用 Prüfer 序列证明:任意一个长度为
以下内容 copy 自
Prüfer 序列可能比你想得还强大。它能创造比凯莱公式更通用的公式。比如以下问题:
一个 [n] 个点 [m] 条边的带标号无向图有 [k] 个连通块。我们希望添加 [k-1] 条边使得整个图连通。求方案数。
证明
设
对于第
现在我们要枚举
好的这是一个非常不喜闻乐见的式子。但是别慌!我们有多元二项式定理:
那么我们对原式做一下换元,设
化简得到
即
这就是答案啦
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现