Prufer 序列
没想到都临近最后一次 NOIP 了,还要被迫学新东西...
不过还好这个知识很好理解。
构造 Prufer 序列:
对于一棵有标号无根树,如果要用一个序列来表示它,那么 Prufer 序列就是其中的一种。
对于一个结点数为 \(n\) 的树,它的 Prefer 序列的长度为 \(n-2\)。
构造方式为:每次选择编号最小的叶子结点,将它连接的点(可以理解为父亲)记录下来,然后将这个叶子结点及其连边删除。
显然可以用堆优化做到 \(O(n\log n)\)。
线性构造:
维护一个指针 \(tag\),初始 \(tag\) 指向最小编号的叶子结点。
设当前最小编号的叶子结点为 \(pos\)
-
记录 \(pos\) 连接的结点 \(x\),并删除 \(pos\) 及其连边;
-
如果 \(x\) 成为新的叶子结点:判断 \(x\) 是否 \(< pos\),如果是,将 \(pos\) 更新为 \(x\),重复步骤 1;
-
否则,将 \(tag\) 自增到一个叶子结点,更新 \(pos\) 为 \(tag\)。
正确性证明:
-
如果 \(x<tag\),由于 \(tag\) 一定是原本的最小叶子,那么此时 \(x\) 一定是最小叶子;
-
如果 \(x>tag\),那么后面 \(tag\) 会扫到它,就不需要操作。
-
每个点最多被扫一次,因此复杂度为 \(O(n)\)。
性质:
-
没出现在 Prufer 序列的结点,在原树中是叶子结点;
-
若一个结点在 Prufer 序列中出现 \(a\) 次,那么它在原树中的度数就是 \(a+1\)
用 Prufer 序列还原无根树:
其实整个过程与构造 Prufer 序列是一样的。
通过性质上面的性质,我们可以得到每个点的度数 \(dg\),以及原树中最小的叶子结点;然后我们将它与序列中第一个数连边,同时删去两个结点的度数。
然后寻找最小编号的度数为 \(1\) 的点,重复上面的步骤。
因此用上面的方法,一样可以做到线性还原。
应用:
- Cayley 公式
一个 \(n\) 个点的有标号完全图,生成树的数量为 \(n^{n-2}\)
因为一棵有标号无根树对应一个 Prufer 序列,\(n-2\) 个位置取值为 \([1\sim n]\)。
给出每个点的度数,问有多少种不同的生成树?
根据上面的性质 2,那么实际上问题就转化为:有 \(n\) 种数,每种数有 \(dg_i-1\) 个,共 \(n-2\) 个,求总排列数。
那么答案就是: