Cod sursa(job #109137)

Utilizator DastasIonescu Vlad Dastas Data 24 noiembrie 2007 19:28:40
Problema Distante Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.82 kb
#include <cstdio>

#define maxn 50002
#define maxm 100002
#define inf 2<<28

FILE *in = fopen("distante.in","r"), *out = fopen("distante.out","w");

//struct muchie
//{
//    int x, y, c;
//};
//
//int t, n, m, s;
//int d[maxn];
//muchie a[maxm];
//
//void go()
//{
//    if ( d[s-1] != 0 )
//    {
//        fprintf(out, "NU\n");
//        return;
//    }
//
//    for ( int i = 0; i < m; ++i )
//        if ( d[a[i].x - 1] + a[i].c < d[a[i].y - 1] )
//        {
//            fprintf(out, "NU\n");
//            return;
//        }
//    fprintf(out, "DA\n");
//
//    return;
//}
//
//int main()
//{
//    fscanf(in, "%d", &t);
//
//    while ( t-- )
//    {
//        fscanf(in, "%d %d %d", &n, &m, &s);
//        for ( int i = 0; i < n; ++i )
//            fscanf(in, "%d", &d[i]);
//
//        for ( int i = 0; i < m; ++i )
//            fscanf(in, "%d %d %d", &a[i].x, &a[i].y, &a[i].c);
//
//        go();
//    }
//
//	return 0;
//}

struct graf
{
    int nod, cost;
    graf *next;
};

int n, m, s;
graf *a[maxn] = {NULL};

int d[maxn]; // d[i] = distanta minima de la sursa la nodul i
int h[maxn]; // heap-ul
int dd[maxn];

void add(int x, int y, int c)
{
    graf *q = new graf;
    q->next = a[x];
    q->nod = y;
    q->cost = c;
    a[x] = q;
}


//void go()
//{
//    if ( d[s-1] != 0 )
//    {
//        fprintf(out, "NU\n");
//        return;
//    }
//
//    for ( int i = 0; i < m; ++i )
//        if ( d[a[i].x - 1] + a[i].c < d[a[i].y - 1] )
//        {
//            fprintf(out, "NU\n");
//            return;
//        }
//    fprintf(out, "DA\n");
//
//    return;
//}

int poz[maxn]; // poz[i] = pozitia nodului i in heap (vectorul h). -1 daca nodul i nu este in heap

int k;
void swap(int x, int y)
{
    int t = h[x];
    h[x] = h[y];
    h[y] = t;
}

void upheap(int what)
{
    int tata;
    while ( what > 1 )
    {
        tata = what >> 1;

        if ( d[ h[tata] ] > d[ h[what] ] )
            swap(tata, what), poz[ h[what] ] = tata, what = tata;
        else
            what = 1;
    }
}

void downheap(int what)
{
    int f;
    while ( what <= k )
    {
        f = what;
        if ( (what<<1) <= k )
            f = what << 1;
        if ( f + 1 <= k && d[ h[f + 1] ] <= d[ h[f] ] )
            ++f;

        if ( d[ h[what] ] > d[ h[f] ] )
            swap(what, f), what = f;
        else
            what = k+1;
    }
}

void dijkstra_heap(int sursa)
{
    for ( int i = 1; i <= n; ++i )
        d[i] = inf, poz[i] = -1;
    d[sursa] = 0;
    poz[sursa] = 1;

    k = 0;
    h[++k] = sursa;

    for ( int i = 1; i <= n; ++i )
    {
        int min = h[1];
        swap(1, k);
        --k;

        downheap(1);

        graf *q = a[min];

        while ( q )
        {
            if ( d[q->nod] > d[min] + q->cost )
            {
                d[q->nod] = d[min] + q->cost;

                if ( poz[q->nod] != -1 )
                    upheap( poz[q->nod] );
                else
                {
                    h[++k] = q->nod;
                    poz[ h[k] ] = k;
                    upheap( k );
                }
            }
            q = q->next;
        }
    }
}

char tk[maxn] = {0};
void dijkstra_clasic(int sursa)
{
    for ( int i = 1; i <= n; ++i )
        d[i] = inf;
    d[sursa] = 0;

    for ( int i = 1; i <= n; ++i )
    {
        int min = inf;
        int poz = 1;
        for ( int j = 1; j <= n; ++j )
            if ( d[j] < min && !tk[j] )
                min = d[j], poz = j;

        tk[poz] = 1;

        graf *q = a[poz];

        while ( q )
        {
            if ( d[q->nod] > d[poz] + q->cost )
                d[q->nod] = d[poz] + q->cost;

            q = q->next;
        }
    }
}

int main()
{
    int t;
    fscanf(in, "%d", &t);

    int x, y, c;
    while ( t-- )
    {
        fscanf(in, "%d %d %d", &n, &m, &s);
        for ( int i = 1; i <= n; ++i )
            fscanf(in, "%d", &dd[i]), a[i] = NULL;

        for ( int i = 0; i < m; ++i )
        {
            fscanf(in, "%d %d %d", &x, &y, &c);
            add(x, y, c);
            add(y, x, c);
        }

//        for ( int i = 1; i <= n; ++i )
//        {
//            printf("%d : ", i);
//            graf *q = a[i];
//            while ( q )
//            {
//                printf("%d ", q->nod);
//                q = q->next;
//            }
//            printf("\n");
//        }
//        printf("\n\n");

        dijkstra_clasic(s);
        int ok = 1;
        for ( int i = 1; i <= n; ++i )
            if ( d[i] != dd[i] )
            {
                fprintf(out, "NU\n");
                ok = 0;
                break;
            }

        if ( ok )
            fprintf(out, "DA\n");
    }

	return 0;
}