Cod sursa(job #838662)

Utilizator sebii_cSebastian Claici sebii_c Data 20 decembrie 2012 11:24:54
Problema Coduri Huffman Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <cstdio>

#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

struct node {
    long long v;
    node *left;
    node *right;

    node(): v(0), left(NULL), right(NULL) {}
    node(long long _v,
         node* _left,
         node* _right): v(_v), left(_left), right(_right) {}
};  

long long total_sum;
vector<pair<int, long long> > sol;
queue<node> elem;
queue<node> huff;

node* getmin()
{
    node *retval;
    if (elem.empty()) {
        retval = &huff.front();
        huff.pop();
    } else if (huff.empty() || elem.front().v < huff.front().v) {
        retval = &elem.front();
        elem.pop();
    } else {
        retval = &huff.front();
        huff.pop();
    }
    
    return retval;
}

void huffman()
{
    while (!elem.empty()) {
        node* left = getmin();
        node* right = getmin();
        huff.push(node((*left).v + (*right).v, left, right));
    }
    while (huff.size() > 1) {
        node* left = getmin();
        node* right = getmin();
        huff.push(node((*left).v + (*right).v, left, right));
    }
}

void preorder(node *root, long long val, int depth)
{
    if (root == NULL)
        return;
    if (root->left == NULL && root->right == NULL) {
        sol.push_back(make_pair(depth, val));
    } else {
        total_sum += root->v;
        preorder(root->left, val << 1, depth + 1);
        preorder(root->right, (val << 1) + 1, depth + 1);
    }
}

int main()
{
    freopen("huffman.in", "r", stdin);
    freopen("huffman.out", "w", stdout);

    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        long long x; scanf("%lld", &x);
        elem.push(node(x, NULL, NULL));
    }
    huffman();
    preorder(&huff.front(), 0, 0);
    printf("%lld\n", total_sum);
    vector<pair<int, long long> >::iterator it;
    for (it = sol.begin(); it != sol.end(); ++it) {
        printf("%d %lld\n", (*it).first, (*it).second);
    }

    return 0;
}