Cod sursa(job #2375815)

Utilizator dacianouaPapadia Mortala dacianoua Data 8 martie 2019 12:26:28
Problema Coduri Huffman Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb
#include <fstream>
#include <queue>
using namespace std;
ifstream fin("huffman.in");
ofstream fout("huffman.out");
queue <int> q,p;
long long v[2000005];
long long ok=1,nrnoduri,a,b,n,x1,x2;
long long cod[200005];
char decarefiu[2000005];
int tata[2000005],lung[2000005];
int main()
{
    fin>>n;//citesc numarul de simboluri
    nrnoduri=n;
    for(int i=1;i<=n;i++){
        fin>>v[i];//citesc nr aparitii simbol
        q.push(i);//le bag in coada
    }
    while(ok){
        if(q.empty()|| p.empty()){//q tine nodurile initiale , p tine nodurile create prin imbinare
            if(q.empty())//daca q e gol ne oucpam acum doar de coada p
            {
                a = p.front();
                p.pop();
                if(p.empty())//daca si p e gol atunci e gata algo
                {
                    ok=0;
                    continue;
                }
                b=p.front();
                p.pop();
            }
            else
            {
                a=q.front();//extragem primele 2 cele mai mici
                q.pop();
                if(q.empty())
                {
                    ok=0;
                    continue;
                }
                b=q.front();
                q.pop();
            }
        }
        else{//daca avem si noduri in q si noduri imbinate in p verificam daca le putem adauga si pe cele din p
            x1=q.front();
            x2=p.front();
            if(v[x1]<v[x2]){
                a=x1;
                q.pop();
                if(q.empty())//daca nu mai avem ce noduri din q sa verificam pentru o potentiala imbinare
                {
                    b=x2;
                    p.pop();
                }
                else
                {
                    x1=q.front();
                    if(v[x1]<v[x2])
                    {
                        b = x1;
                        q.pop();
                    }
                    else
                    {
                        b=x2;
                        p.pop();
                    }
                }
            }
            else
            {
                a=x2;
                p.pop();
                if(p.empty())
                {
                    b=x1;
                    q.pop();
                }
                else
                {
                    x2=p.front();
                    if(v[x1]<v[x2])
                    {
                        b = x1;
                        q.pop();
                    }
                    else
                    {
                        b=x2;
                        p.pop();
                    }
                }
            }
        }
        ++ nrnoduri;//crestem numarul nodurilor obtinute prin imbinare
        tata[a]=nrnoduri;//spunem pt a si b actual nodul al catelea imbinat este tatal
        decarefiu[a]=0;//spunem daca e fiu de stanga/dreapta
        decarefiu[b]=1;
        tata[b]=nrnoduri;
        v[nrnoduri] = v[a]+v[b];//combinam frecventele
        p.push(nrnoduri);//bagam in coada nodurilor obtinute prin imbinare
    }
    a=0;
    for(int k=n+1;k<=nrnoduri;k++){
        a+=v[k];//adunam frecventele totale ale nodurilor obtinute prin imbinare ca sa aflam lungimea
    }
    fout<<a<<'\n';
    for(int i=1;i<=n;i++){
        a=i;
        b=0;
        while(tata[a]!=0)//obtinem codul simbolului al i-lea parcurgand arborele lui Huffman
        {
            lung[i]++;
            cod[lung[i]]=decarefiu[a];
            a=tata[a];
        }
        a=0;
        for(int j=lung[i];j>=1;--j)
            a=a*2+cod[j];//obtinem scrierea in baza 10
        fout<<lung[i]<<" "<<a<<'\n';
    }
    return 0;
}