Cod sursa(job #2766704)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 2 august 2021 22:31:53
Problema Distante Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.96 kb
#include <iostream>
#include <fstream>
#include <vector>

#define NMAX 50000 //cincizeci de mii

using namespace std;

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

int N, M, S;
int dimHeap;

int dist[NMAX + 1];
int distPres[NMAX + 1];
vector < pair<int, int> > G[NMAX + 1];
bool viz[NMAX + 1];
int pozHeap[NMAX + 1];
int origine[NMAX + 1];
int H[NMAX + 1];

int comparareHeap(int first, int second){
    //-1 daca first < second
    //0 egale
    //1 daca first > second

    if(dist[ H[first] ] < dist[ H[second] ]){
        return -1;
    }
    else if(dist[ H[first] ] == dist[ H[second] ]){
        return 0;
    }
    else {
        return 1;
    }
}

void swapHeap(int first, int second){ //pozitiile din heap trebuiesc primite aici!
    swap(H[first], H[second]);
    swap(pozHeap[ origine[first] ], pozHeap[ origine[second] ]);
    swap(origine[first], origine[second]);
}

void sift(int poz){
    //adica in jos
    int son = 1;
    while(son){
        son = 0;

        int left = poz * 2;
        int right = poz * 2 + 1;

        if(left <= dimHeap){
            son = left;
        }
        if(right <= dimHeap && comparareHeap(right, left) < 0){ // right mai mic ca left
            son = right;
        }

        if( son != 0 && comparareHeap(poz, son) == 1 ){ //poz > son
            swapHeap(poz, son);
            poz = son;
        }
        else {
            son = 0;
        }
    }
}

void percolate(int poz){
    //adica in sus

    while(poz != 1 && comparareHeap(poz, poz / 2) < 0){ // poz mai mic ca poz / 2
        swapHeap(poz, poz / 2);
        poz = poz / 2;
    }

}

void adaugareHeap(int node){
    dimHeap++;
    H[dimHeap] = node;
    origine[dimHeap] = node;
    pozHeap[node] = dimHeap;

    percolate(dimHeap);
}

int areCopiiMaiMici(int poz){
    int son = 0;
    int left = poz * 2;
    int right = poz * 2 + 1;

    if(left <= dimHeap){
        son = left;
    }
    if(right <= dimHeap && comparareHeap(right, left) < 0){ //right < left
        son = right;
    }

    if(son == 0){
        return 0;
    }
    else {
        if(comparareHeap(son, poz) < 0){ //son < poz
            return 1;
        }
        else {
            return 0;
        }
    }
}

int areTataMaiMare(int poz){
    if(poz == 1){
        return 0;
    }

    //acum poz sigur nu e radacina
    int father = poz / 2;

    if( comparareHeap(poz, father) < 0 ){ //poz < father
        return 1;
    }
    else {
        return 0;
    }
}

void stergereHeap(int node){
    if(dimHeap == 1 || pozHeap[node] == dimHeap){
        dimHeap--;
        return;
    }

    //un heap cu minim doua elemente aici, unde pozHeap[node] != dimHeap
    int poz = pozHeap[node];

    //printf("Dau swap in heap la (%d, %d)\n", poz, dimHeap);
    //printf("(%d, %d)\n", H[poz], H[dimHeap]);
    swapHeap(poz, dimHeap);
    //printf("(%d, %d)\n\n", H[poz], H[dimHeap]);
    dimHeap--;

    if( areCopiiMaiMici(poz) ){ //e prea sus atunci, il duc jos
        //printf("Dau sift!\n");
        sift(poz);
    }
    else if( areTataMaiMare(poz) ){ //e prea jos atunci, il duc sus
        //printf("Dau percolate!\n");
        percolate(poz);
    }
}

void adaugareVeciniInHeap(int node){
    for(int i = 0; i < G[node].size(); i++){
        int vec = G[node][i].first;
        int cost = G[node][i].second;

        if(!viz[vec]){
            viz[vec] = 1;
            dist[vec] = dist[node] + cost;
            adaugareHeap(vec);
        }
    }
}

void resetareMemorie(){
    for(int i = 1; i <= N; i++){
        viz[i] = 0;
        dist[i] = 0;
    }

    dimHeap = 0;

    for(int i = 1; i <= N; i++){
        G[i].clear();
    }

}

/*
void afisareHeap(){
    for(int i = 1; i <= dimHeap; i++){
        printf("H[ %d ] = %d\n", i, H[i]);
    }
    printf("\n\n");
}
*/

int BFS(int start){
    viz[start] = 1;
    dist[start] = 0;
    adaugareHeap(start);

    while( dimHeap != 0 ){
        //iau varful, adica cel mai apropiat de sursa
        int node = H[1];
        //printf("Aleg %d\n", node);

        if(dist[node] != distPres[node]){
            return 0;
        }

        adaugareVeciniInHeap(node);
        //afisareHeap();

        stergereHeap(node);

        //afisareHeap();
    }
    //printf("\n!!!\n");

    return 1;
}

int main()
{
    int nrTeste;
    fin >> nrTeste;

    for(int test = 1; test <= nrTeste; test++){
        resetareMemorie();

        fin >> N >> M >> S;

        for(int i = 1; i <= N; i++){
            fin >> distPres[i];
        }

        for(int i = 1; i <= M; i++){
            int x, y, cost;
            fin >> x >> y >> cost;

            G[x].push_back( {y, cost} );
            G[y].push_back( {x, cost} );
        }

        if( BFS(S) ){
            fout << "DA\n";
        }
        else {
            fout << "NU\n";
        }


    }

    return 0;
}