Cod sursa(job #821129)

Utilizator brainwashed20Alexandru Gherghe brainwashed20 Data 21 noiembrie 2012 19:14:32
Problema Coduri Huffman Scor 65
Compilator cpp Status done
Runda Arhiva educationala Marime 2.61 kb
#include<fstream>

using namespace std;

#define Nmax 1000100

struct graf {

    long long val;
    int fiu[3];
} G[Nmax * 2];

struct heap {

    long long val, ind;
} H[Nmax * 2];

long long B[Nmax], lg[Nmax], rez;
int N, Q;

void Heap_Up(int k) {

	while(k>1 && H[k].val<H[k/2].val) {
        long long aux;

        aux = H[k].val;
        H[k].val = H[k/2].val;
        H[k/2].val = aux;

        aux = H[k].ind;
        H[k].ind = H[k/2].ind;
        H[k/2].ind = aux;

		k/=2;
	}
}

void insert(long long val, long long ind) {

	H[++Q].val = val;
	H[Q].ind = ind;
	Heap_Up(Q);
}

void Heap_Down(int k) {
	int son = k;
	if(2*k<=Q && H[2*k].val<H[son].val)
		son = 2*k;
	if(2*k+1<=Q && H[2*k+1].val<H[son].val)
		son = 2*k+1;
	if(son!=k) {
	    long long aux;

	    aux = H[k].val;
        H[k].val = H[son].val;
        H[son].val = aux;

        aux = H[k].ind;
        H[k].ind = H[son].ind;
        H[son].ind = aux;

		Heap_Down(son);
	}
}

void erase() {

    int k = 1;
	H[k].val = H[Q].val;
	H[k].ind = H[Q].ind;
	Q--;
	if(k>1 && H[k].val<H[k/2].val)
		Heap_Up(k);
	else
		Heap_Down(k);
}

void read_data() {

    ifstream f("huffman.in");
    int i;

    f>>N;
    for(i=1; i<=N; i++) {
        f>>G[i].val;
        insert(G[i].val, i);
    }
    f.close();
}

void DF(int poz, long long cod, long long nivel) {

    // fiind arbore strict e clar ca daca are un fiu il va avea si pe cel de-al doilea
    if(G[poz].fiu[1]) {
        DF(G[poz].fiu[1], cod*2, nivel+1);
        DF(G[poz].fiu[2], cod*2+1, nivel+1);
        return;
    }
    lg[poz] = nivel;
    B[poz] = cod;
    // adunam in rez suma costurilor nodurilor interne
    rez = (rez + lg[poz] * G[poz].val);
}

void solve() {

    int M, i, cost, nod;

    M = N;
    // cand in Heap ramane o singura valoare inseamna ca s-au adunat toate valorile
    while(Q != 1) {
        ++M;
        // unim cele mai mici 2 noduri existente in Heap
        for(i=1; i<=2; ++i) {
            cost = H[1].val;
            nod = H[1].ind;
            erase();
            G[M].val += cost;
            G[M].fiu[i] = nod;
        }
        /* introducem in Heap noul nod creat care are ca fii cele 2 noduri de cost minim si
        ca valoare suma valorilor celor 2 noduri*/
        insert(G[M].val, M);
    }
    DF(M, 0, 0);
}

void print_rez() {

    int i;
    ofstream g("huffman.out");
    g<<rez<<"\n";
    for(i=1; i<=N; ++i)
        g<<lg[i]<<" "<<B[i]<<"\n";
    g.close();
}

int main() {

    read_data();
    solve();
    print_rez();

    return 0;
}