Prufer序列

一棵大小为 \(n\) 的有标号无根树对应一个长度为 \(n-2\) 值域为 \([1,n]\) 的 Prufer 序列。

故有 Cayley 公式:\(n\) 个点的完全无向图的生成树有 \(n^{n-2}\) 种。

然后是转换:

树到序列

  1. 找到当前树中编号最小的叶子节点,将其父亲节点编号加入序列,并删除该节点。
  2. 如果父亲节点度数变为 \(1\),将父亲节点当作叶子节点加入待删队列。
  3. 重复 1 2 操作直到原树只剩下两个点。

注意到最后 \(n\) 节点一定会保留下来,所以对于无根树的父亲节点可以以 \(n\) 为根做一遍 dfs 得到。

于是显然可以 \(O(n\log n)\) 做。

线性做法是利用了每次删节点最多只会新增一个叶子节点的性质,维护一个指针指向下一个要删的叶子节点。
每次删掉节点后看父亲节点是否变成叶子节点,如果父亲变成了编号小于指针的叶子,那么直接把父亲当作下一个叶子,但指针不动;否则就让指针自增到下一个叶子。

这样指针只会扫一遍,所有边只会遍历一遍,所以是 \(O(n)\)

序列到树

根据树到序列的构造,我们发现每个度数为 \(d\) 的节点都在 Prufer 序列中出现了 \(d-1\) 次。

同样的,我们可以利用这个性质实现序列到树。

  1. 找到序列中没有出现过的点(叶子节点)中编号最小的,序列第 \(i\) 项即为其父亲,然后删除该叶子节点。
  2. 如果父亲节点度数变为 \(1\),将父亲节点当作叶子节点加入待删队列。
  3. 每次 \(i\) 增加并重复 1 2 操作直到序列结束,此时待删序列中有两个点,将编号小的父亲令为 \(n\)(也就是另一个编号大的)。

同样有显然的 \(O(n\log n)\) 做法。

线性做法是一样。


Prufer 序列通常与有度数限制的计树有关,会用到组合数学。

P6086 【模板】Prufer 序列

[HNOI2004]树的计数

[HNOI2008]明明的烦恼

CF156D Clues

posted @ 2022-03-30 18:45  llmmkk  阅读(51)  评论(0编辑  收藏  举报