2168 荷马史诗

2168 荷马史诗

这道题,听说过,因为这个题的名字挺奇葩,还是来练贪心
不过这个题是一个哈夫曼树,比较恶心
哈夫曼树我们也学过,哈夫曼树又叫最优二叉树
我们按照思路就是求一个k进制的哈夫曼编码,平时我们说的哈夫曼为是2进制的,构造的方法很容易,本题也可以用相同的思想
维护什么呢?转换题意,我们要维护的是最短的带权路径和哈夫曼树的高度,然后就是如何维护

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define LL long long 
using namespace std;
struct node
{
    LL w,h;
    node(LL W, LL H)
	{
        w=W,h=H;
    }
};
bool operator<(node a, node b)
{
    if(a.w!=b.w) return a.w>b.w; 
    return a.h>b.h;  //如果长度相等,高度小的优先
} //构造小根堆的操作。
priority_queue<node> q; //优先队列
int n,k,cnt;
LL temp,maxh,ans;

int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
	{
        scanf("%lld",&temp);
        q.push(node(temp,1));
    }
    if((n-1)%(k-1) != 0) cnt=k-1-(n-1)%(k-1);  //判断是否要补空节点
    for (int i=1; i<=cnt; i++)
        q.push(node(0,1)); //补空节点
    cnt+=n;     //cnt为根节点个数(最初每个根节点都为其本身)
    while(cnt>1)
	{
        temp=maxh=0;
        for(int i=1; i<=k; i++)
		{
            temp+=q.top().w;
            maxh=max(maxh,q.top().h);
            q.pop();
        }
        ans+=temp; //维护带权路径长度之和
        q.push(node(temp, maxh+1)); //合并,高度为最高子树高度+1
        cnt-=k-1; //减少根节点
    }
    printf("%lld\n%lld\n",ans,q.top().h-1);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值