Pagini recente » Cod sursa (job #2901249) | Cod sursa (job #1767531) | Cod sursa (job #2454645) | Cod sursa (job #1211864) | Cod sursa (job #1166845)
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long int64;
class HuffmanTree {
public:
static const int NIL;
static const int BASE;
HuffmanTree(const int _v = 0):
v(_v),
edges(vector< vector<int> >(_v, vector<int>())),
father(vector<int>(_v, NIL)),
level(vector<int>(_v, -1)) {}
int Size() const {
return v;
}
int Level(const int x) {
if (level[x] != -1)
return level[x];
if (father[x] == NIL)
return level[x] = 0;
return level[x] = Level(father[x]) + 1;
}
int AddNode() {
edges.push_back(vector<int>());
father.push_back(NIL);
level.push_back(-1);
return v++;
}
void AddEdge(const int from, const int to) {
edges[from].push_back(to);
father[to] = from;
}
vector<int> GetHuffmanCodes() const {
vector<int> codes = vector<int>(v, -1);
int root = NIL;
for (int x = 0; x < v && root == NIL; ++x)
if (father[x] == NIL)
root = x;
DFS(root, 0, codes);
return codes;
}
private:
int v;
vector< vector<int> > edges;
vector<int> father, level;
void DFS(const int x, const int currentCode, vector<int> &codes) const {
codes[x] = currentCode;
for (int i = 0; i < int(edges[x].size()); ++i)
DFS(edges[x][i], BASE * currentCode + i, codes);
}
};
const int HuffmanTree::NIL = -1;
const int HuffmanTree::BASE = 2;
vector<int64> Frequences;
vector<int> Codes;
int64 TotalLength;
HuffmanTree Tree;
template<class Type>
inline Type ExtractFront(queue<Type> &first, queue<Type> &second) {
Type front;
if (first.empty()) {
front = second.front();
second.pop();
} else if (second.empty()) {
front = first.front();
first.pop();
} else {
if (first.front() < second.front()) {
front = first.front();
first.pop();
} else {
front = second.front();
second.pop();
}
}
return front;
}
void Solve() {
Tree = HuffmanTree(0);
queue< pair<int64, int> > terminal, internal;
for (int i = 0; i < int(Frequences.size()); ++i)
terminal.push(make_pair(Frequences[i], Tree.AddNode()));
while (int(terminal.size()) + int(internal.size()) > 1) {
pair<int64, int> x = ExtractFront< pair<int64, int> >(terminal, internal);
pair<int64, int> y = ExtractFront< pair<int64, int> >(terminal, internal);
int z = Tree.AddNode();
Tree.AddEdge(z, x.second);
Tree.AddEdge(z, y.second);
internal.push(make_pair(x.first + y.first, z));
}
Codes = Tree.GetHuffmanCodes();
Codes.resize(int(Frequences.size()));
TotalLength = 0;
for (int i = 0; i < int(Frequences.size()); ++i)
TotalLength += Frequences[i] * Tree.Level(i);
}
void Read() {
ifstream cin("huffman.in");
int n;
cin >> n;
Frequences = vector<int64>(n);
for (int i = 0; i < n; ++i)
cin >> Frequences[i];
cin.close();
}
void Print() {
ofstream cout("huffman.out");
cout << TotalLength << "\n";
for (int i = 0; i < int(Frequences.size()); ++i)
cout << Tree.Level(i) << " " << Codes[i] << "\n";
cout.close();
}
int main() {
Read();
Solve();
Print();
return 0;
}