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-2} \]

也可以表述为:\(n\)个点的本质不同有标号无根树的个数为\(n^{n-2}\)

有标号有根树

直接在无根树中选择一个点作为根即可。或者可以理解为在构造prufer序列的时候剩下两个点,再选一个点作为叶子,另一个作为根。

方案数就是

\[n^{n-1} \]

有标号有根树森林

树的个数确定

假设数的个数为\(m\)

建一个虚点,连这\(m\)个节点,因为一个点的度数是 prufer 序列中的出现次数\(+1\),所以这个虚点要在 prufer 序列中出现 \(m-1\) 次,再加上是 \(n+1\) 个节点的有根树,也就是

\[\binom{n-1}{m-1}n^{n-m}=\binom{n}{m}mn^{n-m-1} \]

数的个数不确定

如果我们不需要确定根的个数,即对所有\(m\)求和得到

\[\sum_{m=1}\binom{n-1}{m-1}n^{n-m}=\sum_{m=0}\binom{n-1}{m}n^{n-1-m}=(n+1)^{n-1} \]

限制度数的无根树

设度数为\(d_i\),方案数是

\[\binom{n-2}{d_i-1}(n-1)^{n-d_i-1} \]

多个点的度数限制可以由此推广

特别的,如果所有点的度数都有限制

\[\binom{n-2}{d_1-1,d_2-1,d_3-1,\cdots,d_n-1}=\frac{(n-2)!}{\prod(d_i-1)!} \]

连通块建树

证明详见 OI wiki

\(k\) 个连通块,每个连通块大小为 \(a_i\),求将这些连通块连成树的方案数。

\(\sum a_i=n\),答案为

\[n^{k-2}\prod a_i \]

posted @ 2021-07-01 20:01  harryzhr  阅读(109)  评论(0编辑  收藏  举报