贪心 - Huffman 树
定义
对于有 个叶子节点的二叉树,定义 为它们的权值, 为从根节点到第 个叶子的路径长度,那么带权路径长度 定义为:
给定一组权值,它们构成的所有树中, 最小的树就是哈夫曼树。
构造
由给定的 个权值创建 个只有一个根的二叉树,得到一个二叉树集合 。
当 时,取出根节点权值最小的两个树,用一个新的根节点连接他们,这个根的权值是取出的两个树根权值之和。
重复构造至 时得到的树就是 Huffman 树。
为什么?首先,对 时,显然得到的是最优的树。
在 Huffman 树中,将最小的两个 调整到相邻的深度最大的地方,答案不会更差。
对 个节点的 Huffman 树,假设 是最小的两个 ,那么一定可以通过调整使得 是相邻的深度最大的节点,即:
我们每次将 合并为 再放入 的过程,就会使得 最大。
假设 是 的一对节点。
按照我们的构造, 一定会优先于 与某个非严格更小的 合并,按照类似的思路, 的深度一定会 的深度。
如果 是叶子节点,它的兄弟不是叶子,那么它的深度会比某个叶子小,所以他的深度比 的深度小。
同样地证明方法可以推广到 叉树,只需要一点需要注意:因为每次操作都会减少 个数,最终剩 个,所以需要满足 。
如果不是这样,我们可以增加若干个 的点,这显然不会影响答案。
Luogu P6033
这就是二叉哈夫曼树最直白的应用。但是,本题并不能用优先队列,会 TLE。
注意到,我们每次都是取出两个最小的数字 并把它们插入序列中。
所以我们插入的数字一定是非严格递增的。所以可以维护两个 queue。
Luogu P2168
这是 叉哈夫曼树,并且选出 个最小的元素,在有相等的情况下尽量让深度小,所以我们以 为第一关键字,深度为第二关键字维护即可。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 喵喵小窝!