Cod sursa(job #1284090)

Utilizator pintilie.andreiPintilie pintilie.andrei Data 6 decembrie 2014 10:56:50
Problema Arbore partial de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.74 kb
#include <cstdio>
#define NMAX 200003
#define MMAX 400005
//min heap
using namespace std;

FILE* fin=fopen("apm.in","r");
FILE* fout=fopen("apm.out","w");

void afisare_heap( int);
void combinare(int,int);
void crearea_heap_combinare( int&);
int extrage_minim(int &n);
void citire();
void afisare();

int n,H[MMAX],m,h[NMAX];
long long cost=0;
int A[NMAX],tata[NMAX]; // retin indicii muchiilor selectate in APM
struct Muchie {int x,y,c;} G[MMAX];
int Find(int x);
void Union(int i,int j);

int main()
{
    int cx,cy,nr=0,mmin;
    citire();
    crearea_heap_combinare(m);
   // afisare_heap(H,m);
    while(nr<n-1)
    {
        mmin=extrage_minim(m);
        cx=Find(G[mmin].x);
        cy=Find(G[mmin].y);
        if(cx!=cy)
        {
            nr++;
            A[nr]=mmin;
            cost+=G[mmin].c;
            Union(cx,cy);
        }
    }
    afisare();
    fclose(fout);
    return 0;
}

void afisare()
{
    int i;
    fprintf(fout,"%lld\n",cost);
    fprintf(fout,"%d\n",n-1);
    for(i=1;i<n;i++)
    {
        fprintf(fout,"%d %d\n",G[A[i]].x,G[A[i]].y);
    }
    fclose(fout);
}

void Union(int i,int j)//i,j sunt radacinile arborilor
{//j fiu al lui i
    if(h[i]<h[j])
        tata[i]=j;
    else if(h[i]>h[j])
        tata[j]=i;
    else //daca is egale
    {
        h[i]++;
        tata[j]=i;
    }
}

int Find(int x)
{
    int rad=x,aux;
    while(tata[rad])
        rad=tata[rad];
    while(tata[x])
    {
        aux=tata[x];
        tata[x]=rad;
        x=aux;
    }
    return rad;
}


void citire()
{
    int i;
    fscanf(fin,"%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        fscanf(fin,"%d%d%d",&G[i].x,&G[i].y,&G[i].c);
        H[i]=i;
    }
}


int extrage_minim(int &n)
{
    int minim;
    minim=H[1];


    H[1]=H[n];
    n--;
    combinare(n,1);
    return minim;
}

void crearea_heap_combinare(int&n)
{
    int i;
    for(i=n/2;i>0;i--) combinare(n,i);
}


void combinare(int n,int i)
{
    //se combina nodul H[i] cu heapurile cu radacinile 2i si 2i+1 obtinand un nou heap cu radacina H[i]
    int x=H[i];//valoare care coboara
    int tata,fiu;
    tata=i;
    //fiu=2*i;
    fiu= i<<1;
    while(fiu<=n)
    {
        if(fiu+1 <= n && G[H[fiu+1]].c < G[H[fiu]].c) fiu++;
        //fiu indica cel mai mic dintre fi
        if(G[H[fiu]].c<G[x].c)
        {
            H[tata]=H[fiu];
            tata=fiu;
            //fiu=tata*2;
            fiu= tata<<1;
        }
        else break;//ma opresc cand am gasit locul potrivit pt x
    }
    H[tata]=x;
}

void afisare_heap(int n)
{
    int i;

    for(i=1;i<=n;i++)
        fprintf(fout,"%d %d %d\n\n", G[H[i]].x,G[H[i]].y,G[H[i]].c);
    fprintf(fout,"\n");
}