原题链接:http://ac.jobdu.com/problem.php?pid=1172
-
题目描述:
-
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
-
输入:
-
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
-
输出:
-
输出权值。
-
样例输入:
-
5 1 2 2 5 9
-
样例输出:
-
37
具有最高优先级的元素最先删除,我感觉我们只需要知道
priority_queue<int> q;
priority_queue< int,vector<int>,greater<int> > q2;
void f(){
int i;
for(i=0;i<5;i++){
q.push(i);
}
for(i=0;i<5;i++){
cout<<q.top()<<" ";
q.pop();
}
cout<<endl;
}
void g(){
int i;
for(i=0;i<5;i++){
q2.push(i);
}
for(i=0;i<5;i++){
cout<<q2.top()<<" ";
q2.pop();
}
cout<<endl;
}
的结果分别是
4 3 2 1 0
0 1 2 3 4
默认的出对顺序是权值较大的,添加了greater<int>之后,就正好相反了
当然调用priority_queue< int,vector<int>,greater<int> >这个数据结构的时候,需要引用
#include <queue>
#include <functional>
哈夫曼树的创建的过程就是每次取出当前最小的两个数,然后相加合并,树增高一层,最后权值就是树高*叶子节点的权值,如本题的1 2 2 5 9,37=(1+2)*4+2*3+5*2+9
(图片来源:http://www.cnblogs.com/mcgrady/p/3329825.html)
我意外的的发现,例如上图求权值,求2 5 7 13的最小带权路径就是(2+5)*3+7*2+13=48
其实也可以这样算,就是所有的非叶子节点之和,即27+14+7=48,测试用例中的37也可以这么算37=19+10+5+3
我的程序就是这么写的,想想也对,非叶子节点不就是所有的叶子节点加起来的吗?理论的证明这个还需要参考
代码如下:
#include <iostream>
#include <functional>
#include <queue>
using namespace std;
int main(int argc, char** argv) {
int n,i;
priority_queue< int,vector<int>,greater<int> >q;
while(cin>>n){
int tmp;
for(i=0;i<n;i++){
cin>>tmp;
q.push(tmp);
}
int ans=0;
while(q.size()!=1){
int num1=q.top();
q.pop();
int num2=q.top();
q.pop();
int result=num1+num2;
ans+=result;
q.push(result);
}
q.pop();
cout<<ans<<endl;
}
return 0;
}
如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步
文章转载请注明出处,请尊重知识产权