Cod sursa(job #838778)

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

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

using namespace std;

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

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

long long tot_sum = 0;
vector<pair<int, long long> > sol;
queue<node *> elem;
queue<node *> huff;

inline node* getmin()
{
    node *retval;
    if (elem.empty()) {
        retval = huff.front();
        huff.pop();
    } else if (huff.empty()) {
        retval = elem.front();
        elem.pop();
    } else {
        if (elem.front()->v <= huff.front()->v) {
            retval = elem.front();
            elem.pop();
        } else {
            retval = huff.front();
            huff.pop();
        }
    }

    return retval;
}

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

void hcode()
{
    while (!huff.empty() || !elem.empty()) {
        node* left = getmin();
        if (huff.empty() && elem.empty()) {
            preorder(left, 0, 0);
            break;
        }
        node* right = getmin();
        huff.push(new node(left->v + right->v, left, right));
        tot_sum += left->v + right->v;
    }
}

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

    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        int x; scanf("%d", &x);
        elem.push(new node(x, NULL, NULL));
    }
    hcode();
    cout << tot_sum << "\n";
    vector<pair<int, long long> >::iterator it;
    for (it = sol.begin(); it != sol.end(); ++it) 
        cout << (*it).first << " " << (*it).second << "\n";

    return 0;
}