哈夫曼树总结

定义带权路径长度为:每个节点的权值*到根的距离 的和

当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。

构造哈夫曼树过程

每次找出权值最小的两个点作为一个新节点的左右儿子,把他们的权值和放回队列中,反复进行这个操作直到得到一个点为止

拓展到 k 叉树

如果把上述过程改为每次选出k个权值最小的贪心的话,会发现最后一次可能会不足k个而导致答案不优,可以通过补充若干0,使得总节点个数mod k-1 = 1

P2168 [NOI2015] 荷马史诗

多叉模板

#include
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct point
{
    ll w,h;
    bool operator < (const point &oth) const
    {
        if(w==oth.w) return h>oth.h;
        return w>oth.w;
    }
};
priority_queue <point> q;
int n,k;
int main()
{
    // freopen("a.in","r",stdin);
    // freopen("a.out","w",stdout);
    scanf("%d%d",&n,&k);
    ll x,ans=0;
    for(int i=1;i<=n;i++) scanf("%lld",&x),q.push((point){x,0});
    while((q.size()-1)%(k-1)!=0) q.push((point){0,0});
    while(q.size()>=k)
    {
        ll sum=0,mx=0;
        for(int i=1;i<=k;i++)
        {
            mx=max(q.top().h,mx);
            sum+=q.top().w;
            q.pop();
        }
        q.push((point){sum,mx+1});
        ans+=sum;
    }
    printf("%lld\n%lld\n",ans,q.top().h);
    return 0;
}

你可能感兴趣的:(哈夫曼树)