Huffman-Tree 学习笔记

又是啃课件的一天

定义

构造一棵含\(n\)个叶子结点的\(k\)叉树, 其中第\(i\)个叶子结点权值\(w_i\), 要求最小化
\(\sum w_i*d_i\), \(d_i\)表示\(i\)结点的深度。

这样的合法的树被称为(k叉)\(Huffman\)

构造方法

增加一些叶子结点为\(0\)的结点, 使得它成为满\(k\)叉树。将\(w\)都丢进小根堆,每次都
取前\(k\)小的\(w\),和为\(s\),建立权值为\(s\)的节点\(p\),令\(p\)成为这\(k\)个结点的父亲, 然后把\(s\)丢入堆。

证明大概就是要保证权值最小在下面,但是如果不是满\(k\)叉树会错,于是就补几个\(0\)\(qwq\)

感性理解下

应用

这个可以压缩文件的,不过打不过专业软件就对了。

Problem1 NOIP2004 合并果子

想不到吧,二叉Huffman树就可以了,二叉并不用补0。

/*
@Date    : 2019-09-06 21:56:05
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
IL int getint()
{
	RG int xi=0;
	RG char ch=gc;
	bool f=0;
	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
	return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
	if(k<0)k=-k,putchar('-');
	if(k>=10)pi(k/10,0);
	putchar(k%10+'0');
	if(ch)putchar(ch);
}
__gnu_pbds::priority_queue<int,greater<int> >p;
int main(void)
{
	int n=gi;
	for(int i=1;i<=n;++i)p.push(gi);
	int ans=0;
	while(p.size()>=2){
		int w1=p.top();p.pop();
		int w2=p.top();p.pop();
		int s=w1+w2;
		ans+=s;
		p.push(s);
	}
	pi(ans);
	return 0;
}

Problem2 NOI2015荷马史诗

k叉Huffman树,维护一下深度就可以了。

所以这玩意除了裸题有什么别的用?

/*
@Date    : 2019-09-06 22:03:12
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
typedef long long ll;
IL ll getint()
{
	RG ll xi=0;
	RG char ch=gc;
	bool f=0;
	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
	return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
	if(k<0)k=-k,putchar('-');
	if(k>=10)pi(k/10,0);
	putchar(k%10+'0');
	if(ch)putchar(ch);
}
typedef pair<ll,int> pll;
__gnu_pbds::priority_queue<pll,greater<pll> >q;
#define fi first
#define se second
#define mp make_pair
int main(void)
{
	int n=gi,k=gi;
	for(int i=1;i<=n;++i)q.push(mp(gi,0));
	while((n-1)%(k-1))q.push(mp(0,0)),++n;
	ll ans=0;
	while(n>1){
		ll sum=0;
		int mh=0;
		for(int i=1;i<=k;++i)sum+=q.top().fi,chkmax(mh,q.top().se),q.pop();
		ans+=sum;
		q.push(mp(sum,mh+1));
		n-=k-1;
	}
	pi(ans,'\n'),pi(q.top().se);
	return 0;
}
posted @ 2019-09-06 22:15  Adscn  阅读(190)  评论(0编辑  收藏  举报