Cod sursa(job #1307884)

Utilizator gabrieligabrieli gabrieli Data 2 ianuarie 2015 23:36:31
Problema Coduri Huffman Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.04 kb
#include <cstdint>
#include <algorithm>
#include <fstream>
#include <queue>
#include <vector>
#include <memory>
#include <map>
using namespace std;

struct Node;

typedef shared_ptr<Node> node_t;

struct Node {
    uint64_t w;
    node_t left;
    node_t right;
    
    Node(uint64_t w, node_t left = nullptr, node_t right = nullptr)
    : w {w}, left {left}, right {right}
    {}
};

uint64_t df(node_t node, map<int, vector<uint64_t>>& alph, uint64_t rep = 0, int h = 0) {
    while (node->left && node->right)
        return  df(node->left, alph, rep << 1, h + 1) +
                df(node->right, alph, (rep << 1) + 1, h + 1);
    
    alph[h].push_back(rep);
    return h * node->w;
}

inline
node_t pop(queue<node_t>& Q_leaf, queue<node_t>& Q_internal) {
    node_t r;
    
    if (Q_leaf.size()) {
        if (Q_internal.size()) {
            if (Q_leaf.front()->w < Q_internal.front()->w) {
                r = Q_leaf.front();
                Q_leaf.pop();
            }
            else {
                r = Q_internal.front();
                Q_internal.pop();
            }
        }
        else {
            r = Q_leaf.front();
            Q_leaf.pop();
        }
    }
    else {
        r = Q_internal.front();
        Q_internal.pop();
    }
    
    return r;
}

int main() {
    ifstream fin("huffman.in");
    ofstream fout("huffman.out");
    
    int n; fin >> n;
    
    // min priority queue
    queue<node_t> Q_leaf, Q_internal;
    for (uint64_t x; n--;) {
        fin >> x;
        Q_leaf.push(make_shared<Node>(x));
    }
    
    // build Huffman tree
    while (Q_leaf.size() + Q_internal.size() > 1) {
        node_t l = pop(Q_leaf, Q_internal),
               r = pop(Q_leaf, Q_internal);
        
        Q_internal.push(make_shared<Node>(l->w + r->w, l, r));
    }
    
    map<int, vector<uint64_t>> alph;   
    fout << df(Q_internal.front(), alph) << '\n';   
       
    for (auto it = alph.rbegin(); it != alph.rend(); ++it)
        for (auto rep : it->second)
            fout << (it->first) << ' ' << rep << '\n';
            
    return 0;
}