Pagini recente » Cod sursa (job #1786155) | Cod sursa (job #40606) | Cod sursa (job #989616) | Cod sursa (job #1756917) | Cod sursa (job #2551632)
#include <cstdint>
#include <fstream>
#include <queue>
#include <vector>
using namespace std;
struct Code
{
int length;
int num;
};
struct Node
{
int id;
int64_t cost = 0;
int symbol = -1;
int zero = -1;
int one = -1;
Node(int id, int64_t cost, int symbol = -1)
: id(id), cost(cost), symbol(symbol) {}
};
using Tree = vector<Node>;
int PopCheapest(queue<int> &q1, queue<int> &q2, const Tree &tree)
{
int res = -1;
if (q1.empty() || (!q2.empty() && tree[q2.front()].cost < tree[q1.front()].cost)) {
res = q2.front();
q2.pop();
} else {
res = q1.front();
q1.pop();
}
return res;
}
void Dfs(const Tree &tree, int node, int length, int num, vector<Code> &codes)
{
if (tree[node].symbol >= 0) {
codes[tree[node].symbol] = (Code){.length = length, .num = num};
}
if (tree[node].zero >= 0) {
Dfs(tree, tree[node].zero, length + 1, (num << 1), codes);
}
if (tree[node].one >= 0) {
Dfs(tree, tree[node].one, length + 1, (num << 1) + 1, codes);
}
}
vector<Code> ExtractCodes(const Tree &tree, int root, int symbols)
{
vector<Code> codes(symbols);
Dfs(tree, root, 0, 0, codes);
return codes;
}
vector<Code> FindCodes(const vector<int> &count)
{
queue<int> q1, q2;
Tree tree;
for (size_t i = 0; i < count.size(); i += 1) {
tree.push_back(Node(i, count[i], i));
q1.push(i);
}
while (q1.size() + q2.size() > 1) {
auto a = PopCheapest(q1, q2, tree);
auto b = PopCheapest(q1, q2, tree);
auto cost = tree[a].cost + tree[b].cost;
tree.push_back(Node(tree.size(), cost));
tree.back().zero = a;
tree.back().one = b;
q2.push(tree.size() - 1);
}
return ExtractCodes(tree, q2.front(), count.size());
}
int64_t FindLength(const vector<Code> &codes, const vector<int> &count)
{
int64_t length = 0;
for (size_t i = 0; i < count.size(); i += 1) {
length += 1LL * count[i] * codes[i].length;
}
return length;
}
int main()
{
ifstream fin("huffman.in");
ofstream fout("huffman.out");
int symbols;
fin >> symbols;
vector<int> count(symbols);
for (auto &c : count) {
fin >> c;
}
auto codes = FindCodes(count);
auto length = FindLength(codes, count);
fout << length << "\n";
for (const auto &code : codes) {
fout << code.length << " " << code.num << "\n";
}
return 0;
}