Cod sursa(job #2653400)

Utilizator irimia_alexIrimia Alex irimia_alex Data 27 septembrie 2020 23:37:38
Problema Coduri Huffman Scor 65
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.09 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* u[2 * NMAX], * v[2 * NMAX];
int usize = 0, vsize = 0, ustart = 0, vstart = 0;

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() {
    if (ustart==usize) {
        node* e = v[vstart];
        ++vstart;
        return e;
    }
    if (vstart==vsize) {
        node* e = u[ustart];
        ++ustart;
        return e;
    }
    if (u[ustart]->fq < v[vstart]->fq) {
        node* e = u[ustart];
        ++ustart;
        return e;
    }
    node* e = v[vstart];
    ++vstart;
    return e;
}

node* Huffman() {
    for (int i = 0;i < n;++i) {
        node* e = new node();
        e->fq = freq[i];
        e->index = i;
        u[usize++] = e;
    }

    while (ustart < usize || vstart < vsize - 1) {
        node* x = extract();
        node* y = extract();
        v[vsize++] = newNode(x, y);
    }

    return v[vstart];

}

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;
}