acwing149
这道题基本逻辑很简单,使用一个优先队列模拟哈夫曼树的建立。有这几个注意点:
从优先队列选结点构建新的节点时要注意判断队列的元素个数,防止出现剩余结点数少于叉数的情况。
每次选结点要先按照权值从小到大找结点,若权值相同再按照结点的深度从小到大找。可以自定义优先队列的比较函数,也可以使用pair来存储这两个属性。
对多叉树而言,叶子的个数n与叉数k必须满足以下条件:
\((n-1)\%(k-1)=0\)
所以要先加入一些虚结点,使之满足该条件
代码如下:
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
//用于优先队列
struct node {
ll w; //权值
int depth; //深度
node(ll _w,int _d):w(_w),depth(_d){}
};
//用于结点间比较的函数
struct cmp {
bool operator()(const struct node& a, const struct node& b) {
if (a.w != b.w) return a.w > b.w;
return a.depth > b.depth;
}
};
//优先队列
priority_queue<struct node, vector<struct node>, cmp> pq;
int main(void) {
//n种单词,k进制str
int n, k; cin >> n >> k;
for (int i = 0; i < n; i++) {
ll w; cin >> w; pq.push(node(w,0));
}
//对于多叉树,加入虚的叶子结点(坑)
while ((n - 1) % (k - 1)) {
n++;
pq.push(node(0, 0));
}
//ans:总的最短长度 minlen:最长字串的最短长度
ll ans=0,minlen=0;
while (pq.size()>1) {
//储存k个元素中depth的最大值
int maxdepth = 0;
ll tempw=0;
//pop出k个元素
for (int i = 0; i < k; i++) {
//对于剩余元素不到k个特殊处理
if (pq.size() == 0) break;
tempw += pq.top().w;
if (maxdepth < pq.top().depth) maxdepth = pq.top().depth;
pq.pop();
}
maxdepth++;
//更新ans和minlen
ans += tempw;
if(minlen<maxdepth) minlen = maxdepth;
//加入新的结点
pq.push(node(tempw, maxdepth));
}
cout << ans << endl << minlen << endl;
}

浙公网安备 33010602011771号