【模板】哈夫曼树 && 洛谷 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;
}