Prufer序列
一棵大小为 \(n\) 的有标号无根树对应一个长度为 \(n-2\) 值域为 \([1,n]\) 的 Prufer 序列。
故有 Cayley 公式:\(n\) 个点的完全无向图的生成树有 \(n^{n-2}\) 种。
然后是转换:
树到序列
- 找到当前树中编号最小的叶子节点,将其父亲节点编号加入序列,并删除该节点。
- 如果父亲节点度数变为 \(1\),将父亲节点当作叶子节点加入待删队列。
- 重复 1 2 操作直到原树只剩下两个点。
注意到最后 \(n\) 节点一定会保留下来,所以对于无根树的父亲节点可以以 \(n\) 为根做一遍 dfs 得到。
于是显然可以 \(O(n\log n)\) 做。
线性做法是利用了每次删节点最多只会新增一个叶子节点的性质,维护一个指针指向下一个要删的叶子节点。
每次删掉节点后看父亲节点是否变成叶子节点,如果父亲变成了编号小于指针的叶子,那么直接把父亲当作下一个叶子,但指针不动;否则就让指针自增到下一个叶子。
这样指针只会扫一遍,所有边只会遍历一遍,所以是 \(O(n)\)。
序列到树
根据树到序列的构造,我们发现每个度数为 \(d\) 的节点都在 Prufer 序列中出现了 \(d-1\) 次。
同样的,我们可以利用这个性质实现序列到树。
- 找到序列中没有出现过的点(叶子节点)中编号最小的,序列第 \(i\) 项即为其父亲,然后删除该叶子节点。
- 如果父亲节点度数变为 \(1\),将父亲节点当作叶子节点加入待删队列。
- 每次 \(i\) 增加并重复 1 2 操作直到序列结束,此时待删序列中有两个点,将编号小的父亲令为 \(n\)(也就是另一个编号大的)。
同样有显然的 \(O(n\log n)\) 做法。
线性做法是一样。
Prufer 序列通常与有度数限制的计树有关,会用到组合数学。