Cod sursa(job #2653519)

Utilizator irimia_alexIrimia Alex irimia_alex Data 28 septembrie 2020 13:10:26
Problema Coduri Huffman Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.95 kb
#include <iostream>
#include <fstream>
#include <queue>
#define NMAX 1000001

using namespace std;

struct node {
    long long int fq = 0;
    int left = 0, right = 0;
};

int freq[NMAX] = { 0 }, n;
pair<int, long long int> res[NMAX];
node v[3 * NMAX];
int usize = 0, vsize = 0, ustart = 0, vstart = 0;

node newNode(node x, int xi, node y, int yi) {
    node e;
    e.left = xi;
    e.right = yi;
    e.fq = x.fq + y.fq;

    return e;
}

int extract() {
    int index;
    if (ustart == usize) {
        index = vstart;
        ++vstart;
    }
    else if (vstart == vsize) {
        index = ustart;
        ++ustart;
    }
    else if (v[ustart].fq < v[vstart].fq) {
        index = ustart;
        ++ustart;
    }
    else {
        index = vstart;
        ++vstart;
    }
    return index;
}

int Huffman() {
    for (int i = 0;i < n;++i) {
        node e;
        e.fq = freq[i];
        e.left = e.right = i;
        v[usize++] = e;
    }
    vstart = usize;
    vsize = usize;

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

    return vstart;

}

void dfs(int root, int len, long long int val) {
    node e = v[root];
    if (e.right == e.left) {
        res[e.left] = { len,val };
        return;
    }
    dfs(v[root].left, len + 1, (val << 1) | 0);
    dfs(v[root].right, len + 1, (val << 1) | 1);
}

int main() {

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

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

    int 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';

    return 0;
}