Prufer 序列

Prufer 序列可以将一个带标号\(n\)个节点的树用\([1,n]\)中的\(n-2\)个整数表示,即\(n\)个点的完全图的生成树与长度为\(n-2\)值域为\([1,n]\)的数列构成的双射。

Prufer 序列可以方便的解决一类树相关的计数问题,比如凯莱定理\(n\)个点的完全图的生成树有 \(n^{n-2}\)个。注意这是定根树或无根树,根不定还要\(\times n\)

对树构造 Prufer 序列

Prufer 是这样构造的:

每次选择一个编号最小的叶节点并删掉它,然后在序列中记录下它连接到的那个节点。

重复\(n-2\)次后就只剩下两个节点,算法结束。

\(\mathcal O(n \log n)\)

显然,使用堆可以做到\(O(n\log n)\)的复杂度。

\(\mathcal O(n)\)

使用一个指针代替堆找最小值,可以做到 \(\mathcal O(n)\) 的复杂度。

具体而言,指针指向编号最小的叶节点。每次删掉它之后,如果产生了新的叶节点且编号比指针指向的更小,则直接继续删掉,否则自增找到下一个编号最小的叶节点。

Prufer 序列的性质

从上述构造 Prufer 序列的过程可以看出 Prufer 序列具有以下两个性质:

  1. 在构造完 Prufer 序列后原树中会剩下两个节点,其中一个一定是编号最大的点 \(n\)
  2. 每个节点在序列中出现的次数是其度数减 1,因此没有出现的就是叶节点。

用 Prufer 序列构造树

根据 Prufer 序列的性质,我们可以得到原树上每个点的度数。

每次我们选择一个编号最小的度数为 1 的节点,与当前枚举到的 Prufer 序列的点连接,然后同时减掉两个点的度数。重复 \(n-2\)次后就只剩下两个度数为 1 的节点,其中一个是\(n\),把它们连接起来即可。

\(\mathcal O(n \log n)\)

同样地,显然,使用堆可以做到 \(O(n\log n)\) 的复杂度。

\(\mathcal O(n)\)

类似地,使用一个指针代替堆找最小值,可以做到 \(\mathcal O(n)\) 的复杂度。

具体而言,指针指向编号最小的度数为 1 的节点。每次将它与当前枚举到的 Prufer 序列的点连接之后,如果产生了新的度数为 1 的节点且编号比指针指向的更小,则直接继续将它与下一个 Prufer 序列的点连接,否则自增找到下一个编号最小的度数为 1 的节点。

------摘自洛谷大佬\(xht\)

posted on 2022-10-06 13:34  Bwzhh  阅读(63)  评论(0编辑  收藏  举报