prufer序列学习笔记
prufer序列简介
将一棵无根树和一个值域在 \([1,n]\) 之间的长为 \(n-2\) 的序列 一一对应
构造
每次选择一个标号最小的叶子结点删除掉,将删除的节点的父亲记录在 prufer 序列的末尾。重复此过程。
使用堆维护的话复杂度是 \(O(n\log n)\) 的。
线性构造
维护一个单调递增的指针 \(p\),初始时 \(p\) 指向编号最小的叶结点。每次我们删除一个节点的时候,如果其父亲变成叶子,记其父亲为\(x\)。若\(x<p\),则下一步直接删除\(x\),继续进行。否则的话让指针 \(p\) 自增直到遇到一个未被删除叶结点为止。证明也很简单,在\(p\)之前的度数为\(1\)的点要么已经被\(p\)自增的时候扫过去了,要么是扫过去了以后变成叶子,会被贪心的先选择。
时间复杂度\(O(n)\)
还原
整体过程大概就是构造的逆变换。有一个关键性质是,设\(d_i\)为\(i\)的度数,那么\(i\)在prufer序列中的出现次数为\(d_i-1\)。我们可以根据prufer序列确定每一个顶点的度数。
朴素做法还是用堆维护编号最小的叶子节点,从前往后依次扫描prufer序列,当前prufer序列中的元素就是编号最小的叶子的父亲。时间复杂度 \(O(n\log n)\)
线性还原
类似线性构造,我们将用堆维护编号最小的叶子换成单调递增的指针+贪心判断即可。时间复杂度\(O(n)\)
应用
Cayley 公式
用于prufer序列与无根树的一一对应关系,我们可以得到
有\(n\)个点的完全图的有标号生成树个数为
也可以表述为:有\(n\)个点的本质不同有标号无根树的个数为\(n^{n-2}\)
有标号有根树
直接在无根树中选择一个点作为根即可。或者可以理解为在构造prufer序列的时候剩下两个点,再选一个点作为叶子,另一个作为根。
方案数就是
有标号有根树森林
树的个数确定
假设数的个数为\(m\)
建一个虚点,连这\(m\)个节点,因为一个点的度数是 prufer 序列中的出现次数\(+1\),所以这个虚点要在 prufer 序列中出现 \(m-1\) 次,再加上是 \(n+1\) 个节点的有根树,也就是
数的个数不确定
如果我们不需要确定根的个数,即对所有\(m\)求和得到
限制度数的无根树
设度数为\(d_i\),方案数是
多个点的度数限制可以由此推广
特别的,如果所有点的度数都有限制
连通块建树
证明详见 OI wiki
有 \(k\) 个连通块,每个连通块大小为 \(a_i\),求将这些连通块连成树的方案数。
记 \(\sum a_i=n\),答案为