【模板】哈夫曼树 && 洛谷 P2168 [NOI2015] 荷马史诗
传送门
解题思路
哈夫曼树(Huffman Tree),就是一棵树满足叶子节点的权值*到根节点的距离的和最小的树。
一开始假设整个图没有任何连边。
然后贪心思想,每次新建一个节点,取k个权值最小的节点作为这个节点的儿子(相当于把节点合并)。
这样每次少k-1个节点,会导致最后一次合并不满k个节点。
这样很显然是不优的。
所以可以一开始补充上几个空节点。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+5;
struct node{
long long dep,w,sum;
bool operator >(const node x)const{
return w!=x.w?w>x.w:dep>x.dep;
}
}a[10*maxn];
priority_queue<node,vector<node>,greater<node> > q;
long long n,k,res;
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i].w,a[i].dep=a[i].sum=0;
if((n-1)%(k-1)!=0) res=(k-1)-(n-1)%(k-1);
for(int i=1;i<=res;i++){
a[++n].dep=-2;
a[n].w=0;
a[n].sum=0;
}
for(int i=1;i<=n;i++) q.push(a[i]);
while(q.size()>1){
node x;
x.dep=-1;
x.w=0;
x.sum=0;
for(int i=1;i<=k;i++){
x.w+=q.top().w;
x.dep=max(x.dep,q.top().dep+1);
x.sum+=q.top().sum;
q.pop();
}
x.sum+=x.w;
q.push(x);
}
cout<<q.top().sum<<endl<<q.top().dep;
return 0;
}