Cod sursa(job #1166845)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 3 aprilie 2014 21:06:46
Problema Coduri Huffman Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.5 kb
#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;
}