随笔 - 26  文章 - 0  评论 - 0  阅读 - 2560 

Prufer 序列

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

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

对树构造 Prufer 序列

Prufer 是这样构造的:

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

重复n2次后就只剩下两个节点,算法结束。

O(nlogn)

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

O(n)

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

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

Prufer 序列的性质

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

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

用 Prufer 序列构造树

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

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

O(nlogn)

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

O(n)

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

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

------摘自洛谷大佬xht

posted on   Bwzhh  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示