#1111 : Huffman编码
时间限制:
30000ms
单点时限:
3000ms
内存限制:
256MB
-
5 1 1 2 1 1 3 1 1 1 4 1 1 1 1 4 1 1 2 2
样例输出
-
1 2 12 24 24
描述
给定一个大小为n的字符集Σ中每个字符出现的频数,求不同的Huffman编码的数量模109 + 7。
一个编码是一个从Σ到01字符串的函数。 一个Huffman编码是一个由以下过程生成的编码:
初始时每个字符为一个集合。初始时所有字符对应到空字符串。一个集合S的频数w(S)定义为S内所有字符的频数的和。 不断进行以下操作直到只剩下一个集合:
选择两个不同的集合A和B使得w(A) + w(B)最小。将A内所有字符对应到的字符串前端加上'0'。将B内所有字符对应到的字符串前端加上'1'。添加一个集合C,为A和B的并。删除A和B。
两个编码不同当且仅当存在一个字符对应到的01字符串不同。
输入
第一行,T,测试点个数。下面T个测试点。
对于每个测试点,第一行,n,为字符集Σ的大小。 第二行,n个整数w1, ..., wn. 其中wi为第i个字符的频数。
1 ≤ n ≤ 106. 所有n的和 ≤ 106. 1 ≤ wi ≤ 106.
输出
T行。每行为对应测试点的答案。
1
2
5
8
12
代码如下:
#include<iostream>
using namespace std;
#include<functional>
#include<queue>
#include<vector>
struct node
{
int x;
vector<int> y;
friend bool operator < (node a, node b){return a.x>b.x;}
};
int main()
{
int cnt;
cin>>cnt;
while(cnt--)
{
priority_queue<node> que;
int len;
cin>>len;
vector<int> chang(len,0);
vector<int> quanzhong;
for(int i=0;i<len;++i)
{ int quan;
node newnode;
cin>>quan;
quanzhong.push_back(quan);
newnode.x=quan;
newnode.y.push_back(i);
que.push(newnode);
}
while(!que.empty())
{
if(que.size()==1)
{
//node a=que.top();
que.pop();
//int sz=a.y.size();
//for(int i=0;i<sz;++i)
// chang[a.y[i]]++;
if(len==1)
chang[0]++;
}else{
node a=que.top();
que.pop();
node b=que.top();
que.pop();
int sz=a.y.size();
for(int i=0;i<sz;++i)
chang[a.y[i]]++;
sz=b.y.size();
for(int i=0;i<sz;++i)
chang[b.y[i]]++;
node c;
c.x=a.x+b.x;
c.y.insert(c.y.end(),a.y.begin(),a.y.end());
c.y.insert(c.y.end(),b.y.begin(),b.y.end());
que.push(c);
}
}
int res=0;
for(int i=0;i<len;++i)
res+=chang[i]*quanzhong[i];
cout<<res<<endl;
}
return 0;
}