Cod sursa(job #271784)

Utilizator stocarulCosmin-Mihai Tutunaru stocarul Data 5 martie 2009 22:27:31
Problema Distante Scor 0
Compilator c Status done
Runda Arhiva de probleme Marime 4.58 kb
#include<stdio.h>   
#define infile "distante.in"   
#define outfile "distante.out"   
#define nmax 50*1001   
#define mmax 200*1001   
#define inf ~(1<<31)   
struct lista   
    {   
    int n,p,c; //nodul, pozitia si costul   
    } l[mmax]; //lista   
struct nod   
    {   
    int p,ph,c,cb; //pozitia, pozitia din heap, costul minim si costul minim gasit de bronzanel   
    } n[nmax]; //nodurile   
int h[nmax]; //min-heap-ul   
int s,nrl,nrn,nrh;   
  
//adauga arcul (x,y) cu costul c   
void add(int m, int x, int y, int c)   
    {   
    l[m].n=y; l[m].c=c; l[m].p=n[x].p; n[x].p=m;   
    }   
  
void citire()   
    {   
    int i,x,y,c;   
    scanf("%d %d %d",&nrn,&nrl,&s); //numarul de noduri, muchii si nodul de start   
    for(i=1;i<=nrn;i++) scanf("%d",&n[i].cb); //costurile lui Bronzanel   
    for(i=1;i<=nrl;i++)   
        {   
        scanf("%d %d %d\n",&x,&y,&c); //(x,y) cu c   
        add(2*i-1,x,y,c); //(x,y) cu c   
        add(2*i,y,x,c); //(y,c) cu c   
        }   
    }   
 
 void golire()
	{
	int i;
	for(i=1;i<=nrn;i++) n[i].p=n[i].ph=0; //golim aceste doua pozitii
	}

//adaugam nodul x in heap   
void add_heap(int x)   
    {   
	nrh++; //facem loc in heap 
    int f=nrh,t=nrh/2; //fiul si tatal     
    while(t&&n[h[t]].c>n[x].c) //cat timp are tata   
        {   
        h[f]=h[t]; n[h[f]].ph=f; //coboram tatal peste fiu   
        f=t; t=f/2; //refacem tatal si fiul   
        }   
    h[f]=x; n[h[f]].ph=f; //adaugam nodul in heap la pozitia corecta   
    }   
  
//combina nodul cu cei doi fi, a.i. sa refacem heap-ul   
void comb_heap(int x)   
    {   
    int t=x,f=2*x; //tatal si fiul   
    while(f<=nrh)   
        {   
        if(f<nrh&&n[h[f]].c>n[h[f+1]].c) f++; //e mai mic al doilea fiu   
        if(n[h[f]].c<n[x].c)   
            {   
            h[t]=h[f]; n[h[t]].ph=t; //urcam copilul peste tatal   
            t=f; f=2*t; //tatal si fiul   
            }   
        else f=nrh+1; //oprim cautarea   
        }   
    h[t]=x; n[h[t]].ph=t; //plasam la pozitia corecta   
    }   
  
//refac heap-ul din pozitia x (x e pozitia din heap)   
void refac_heap(int x)   
    {   
    int f=x,t=x/2; //fiul si tatal   
    x=h[x]; //punem acum in x nodul   
    while(t) //cat timp are tata   
        {   
        if(n[h[t]].c>n[x].c) //tatal e mai mare   
            {   
            h[f]=h[t]; n[h[f]].ph=f; //coboram tatal peste fiu   
            f=t; t=f/2; //refacem tatal si fiul   
            }   
        else t=0; //oprim cautarea   
        }   
    h[f]=x; n[h[f]].ph=f; //adaugam nodul in heap la pozitia corecta   
    }   
  
//extrage primul element din heap   
int extrag_heap()   
    {   
    int v=h[1]; n[v].ph=0; //nodul ce il scoatem   
    h[1]=h[nrh--]; //punem ultimul element in locul lui   
    comb_heap(1); //refacem heap-ul   
    return v; //returnam valoarea   
    }   
  
void initializare()   
    {   
    int ul;   
    nrh=0; //heap-ul devine gol   
    for(ul=1;ul<=nrn;ul++) n[ul].c=inf; //initial avem costul inifinit   
    n[s].c=0; n[s].ph=-1; //la nodul sursa avem costul 0   
    for(ul=n[s].p;ul;ul=l[ul].p) //trecem la copii lui s   
        {   
        n[l[ul].n].c=l[ul].c; //salvam costul cu care ajungem   
        add_heap(l[ul].n); //il adaugam in heap   
        }   
    }   
  
void dijkstra()   
    {   
    int x,ul;   
    while(nrh) //cat timp avem noduri in heap   
        {   
        x=extrag_heap();   
        for(ul=n[x].p;ul;ul=l[ul].p) //trecem la toti fii lui   
            if(n[x].c+l[ul].c<n[l[ul].n].c) //ajungem cu un cost mai mic   
                {   
                n[l[ul].n].c=n[x].c+l[ul].c; //salvam noul cost   
                if(!n[l[ul].n].ph) add_heap(l[ul].n); //nu este in heap...il adaugam   
                else if(n[l[ul].n].ph>0) refac_heap(n[l[ul].n].ph); //refacem heap-ul dupa modificare   
                }   
        }   
    }   
 
int compara()
	{
	int i;
	for(i=1;i<=nrn;i++)
		if(n[i].c!=n[i].cb)
			return 0; //sunt diferite
	return 1;
	}
int main()   
{   
int t;   
freopen(infile,"r",stdin);   
freopen(outfile,"w",stdout);   
  
scanf("%d\n",&t); //numarul de teste   
while(t--) //rezolvam testele   
    {
	golire();
    citire();   
    if(n[s].cb) printf("NU\n"); //nodul de start trebuie sa aibe costul 0   
    else   
        {   
        initializare();   
        dijkstra(); //facem distanta minima
		if(compara()) printf("DA\n"); else printf("NU\n");
        }   
    }   
  
fclose(stdin);   
fclose(stdout);   
return 0;   
}