Prufer 序列

没想到都临近最后一次 NOIP 了,还要被迫学新东西...

不过还好这个知识很好理解。


构造 Prufer 序列:

对于一棵有标号无根树,如果要用一个序列来表示它,那么 Prufer 序列就是其中的一种。

对于一个结点数为 \(n\) 的树,它的 Prefer 序列的长度为 \(n-2\)

构造方式为:每次选择编号最小的叶子结点,将它连接的点(可以理解为父亲)记录下来,然后将这个叶子结点及其连边删除。

显然可以用堆优化做到 \(O(n\log n)\)

线性构造:

维护一个指针 \(tag\),初始 \(tag\) 指向最小编号的叶子结点。

设当前最小编号的叶子结点为 \(pos\)

  1. 记录 \(pos\) 连接的结点 \(x\),并删除 \(pos\) 及其连边;

  2. 如果 \(x\) 成为新的叶子结点:判断 \(x\) 是否 \(< pos\),如果是,将 \(pos\) 更新为 \(x\),重复步骤 1;

  3. 否则,将 \(tag\) 自增到一个叶子结点,更新 \(pos\)\(tag\)

正确性证明:

  • 如果 \(x<tag\),由于 \(tag\) 一定是原本的最小叶子,那么此时 \(x\) 一定是最小叶子;

  • 如果 \(x>tag\),那么后面 \(tag\) 会扫到它,就不需要操作。

  • 每个点最多被扫一次,因此复杂度为 \(O(n)\)


性质:

  1. 没出现在 Prufer 序列的结点,在原树中是叶子结点;

  2. 若一个结点在 Prufer 序列中出现 \(a\) 次,那么它在原树中的度数就是 \(a+1\)


用 Prufer 序列还原无根树:

其实整个过程与构造 Prufer 序列是一样的。

通过性质上面的性质,我们可以得到每个点的度数 \(dg\),以及原树中最小的叶子结点;然后我们将它与序列中第一个数连边,同时删去两个结点的度数。

然后寻找最小编号的度数为 \(1\) 的点,重复上面的步骤。

因此用上面的方法,一样可以做到线性还原。

代码


应用:

  1. Cayley 公式

一个 \(n\) 个点的有标号完全图,生成树的数量为 \(n^{n-2}\)

因为一棵有标号无根树对应一个 Prufer 序列,\(n-2\) 个位置取值为 \([1\sim n]\)

给出每个点的度数,问有多少种不同的生成树?

根据上面的性质 2,那么实际上问题就转化为:有 \(n\) 种数,每种数有 \(dg_i-1\) 个,共 \(n-2\) 个,求总排列数。

那么答案就是:

\[\frac{(n-2)!}{\prod_{i=1}^{n} (dg_i-1)!} \]

posted @ 2022-11-22 19:33  zuytong  阅读(47)  评论(0编辑  收藏  举报