哈夫曼树(周灵猪)

洛谷2168荷马史诗

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
typedef pair<long long, long long> aii;
priority_queue<aii, vector<aii>, greater<aii>> que;
int n, k, Num = 0;
long long Length = 0, Ans = 0, x;
int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        que.push(aii(x,1));//节点的权值,层数//初始时候每个节点都是第一层
    }
    if ((n - 1) % (k - 1) != 0)//
        Num = k - 1 - (n - 1) % (k - 1);//当结点不够时,插入值为零的虚节点,不然算出来可能不是最优解
    for (int i = 1; i <= Num; i++)//插入虚节点,其实就是因为完全二叉树的长度最长,所以要弄成完全二叉树那样,而不能像普通哈夫曼树
        que.push(aii(0,1));
    Num += n;//代表一共有多个元素
    while(Num != 1) 
    {
        aii a;
        long long Temp = 0, Max_h = 0;
        for (int i = 1; i <= k; i++) //几进制就是拿几个点,比如二进制子树可以有两个分别是0,1路径编号,要是三就是0,1,2,
        {
            a = que.top();
            Temp += a.first;//合并后的最大值
            Max_h = max(Max_h, a.second);//计算最大层数
            que.pop();
        }//合并前k个元素
        Ans += Temp;//最短长度就是每次合并后的值的和
        que.push(aii(Temp,Max_h+1));//层数加以
        Num -= k;//节点-k因为拿出去了多少个点
        Num++;//节点+1因为放回去了
    }
    Length = que.top().second - 1;
    cout << Ans << endl;
    cout << Length;
    return 0;
}

后面

这个是最优解的哈夫曼树就是完全K叉树的模样,如果不是要求最解其实很结点

每次都是将k个节点合并为1个(减少k-1个),一共要将n个节点合并为1个,如果(n-1)%(k-1)!=0 则最后一次合并时不足k个。也就表明了最靠近根节点的位置反而没有被排满,因此我们需要加入k-1-(n-1)%(k-1)个空节点使每次合并都够k个节点(也就是利用空节点将其余的节点挤到更优的位置上)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值