Cod sursa(job #2653399)

Utilizator irimia_alexIrimia Alex irimia_alex Data 27 septembrie 2020 23:17:13
Problema Coduri Huffman Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.07 kb
#include <iostream>
#include <fstream>
#include <queue>
#define NMAX 1000001

using namespace std;

struct node {
    int index = -1;
    long long int fq = 0;
    node* left = nullptr, * right = nullptr;
};

int freq[NMAX] = { 0 }, n;
pair<int, long long int> res[NMAX];

node* newNode(node* x, node* y) {
    node* e = new node();
    e->left = x;
    e->right = y;
    e->fq = x->fq + y->fq;

    return e;
}

node* extract(deque<node*>& u, deque<node*>& v) {
    if (u.empty()) {
        node* e = v.back();
        v.pop_back();
        return e;
    }
    if (v.empty()) {
        node* e = u.back();
        u.pop_back();
        return e;
    }
    if (u.back()->fq < v.back()->fq) {
        node* e = u.back();
        u.pop_back();
        return e;
    }
    node* e = v.back();
    v.pop_back();
    return e;
}

node* Huffman() {
    deque<node*> u, v;
    for (int i = n - 1;i >= 0;--i) {
        node* e = new node();
        e->fq = freq[i];
        e->index = i;
        u.push_back(e);
    }

    while (!u.empty() || v.size() > 1) {
        node* x = extract(u, v);
        node* y = extract(u, v);
        v.push_front(newNode(x, y));
    }

    return v.back();

}

void dfs(node* root,int len,long long int val) {
    if (root->index != -1) {
        res[root->index] = { len,val };
        return;
    }
    dfs(root->left, len + 1, (val << 1) | 0);
    dfs(root->right, len + 1, (val << 1) | 1);
}

void erase(node* root) {
    if (root == nullptr) return;
    erase(root->left);
    erase(root->right);
    delete root;
}

int main() {
    
    ifstream fin("huffman.in");
    ofstream fout("huffman.out");

    fin >> n;
    for (int i = 0;i < n;++i)
        fin >> freq[i];

    node* root = Huffman();
    dfs(root, 0, 0);

    long long int lg = 0;
    for (int i = 0;i < n;++i)
        lg += (long long int)freq[i] * res[i].first;

    fout << lg << '\n';

    for (int i = 0;i < n;++i)
        fout << res[i].first << ' ' << res[i].second << '\n';

    erase(root);

    return 0;
}