Cod sursa(job #771429)

Utilizator rvnzphrvnzph rvnzph Data 25 iulie 2012 22:43:35
Problema Distante Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.8 kb
#include <fstream>
#include <vector>

#define NLen 0x10000
#define inf 0x7fffffff

using namespace std;

struct graf
{
    int adj, cost;
};

ifstream fi;
ofstream fo;

vector < graf > G[NLen];

int DIST[NLen];
int D[NLen];
int h[NLen];
int pos[NLen];
int use[NLen];

int N;

inline graf make_conn(int x, int y)
{
    graf ret;
    ret.adj = x;
    ret.cost = y;

    return ret;
}

inline void Push_Heap(int nod)
{
    h[ ++ h[0] ] = nod;
    pos[nod] = h[0];
}

inline void Up_Heap(int nod)
{
    int Old = h[nod];

    for(; nod > 1 && DIST[ h[nod >> 1] ] > DIST[Old]; nod >>= 1)
    {
        h[nod] = h[nod >> 1];
        pos[ h[nod] ] = nod;
    }

    h[nod] = Old;
    pos[Old] = nod;
}

inline void Down_Heap(int nod)
{
    int Old = h[nod], L, R;

    while(1)
    {
        L = nod << 1;
        R = L + 1;

        if(R <= h[0] && DIST[ h[L] ] > DIST[ h[R] ] && DIST[ h[R] ] < DIST[Old])
        {
            h[nod] = h[R];
            pos[ h[nod] ] = nod;
            nod = R;
        }
        else
        if(L <= h[0] && DIST[ h[L] ] < DIST[Old])
        {
            h[nod] = h[L];
            pos[ h[nod] ] = nod;
            nod = L;
        }
        else
        {
            h[nod] = Old;
            pos[ h[nod] ] = nod;
            return;
        }
    }
}

inline void Pop_Heap(int nod)
{
    if(h[0] == nod)
    {
        -- h[0];
        return;
    }

    h[nod] = h[ h[0] -- ];
    pos[ h[nod] ] = nod;

    if(nod > 1 && DIST[ h[nod >> 1] ] > DIST[ h[nod] ]) Up_Heap(nod);
    else Down_Heap(nod);
}

inline int dij(int nod)
{
    for(int i = 1; i <= N; ++ i)
    {
        DIST[i] = inf;
        h[i] = 0;
        pos[i] = 0;
        use[i] = 0;
    }

    DIST[nod] = 0;
    use[nod] = 1;

    h[0] = 1;
    h[1] = nod;
    pos[nod] = 1;

    while(h[0])
    {
        nod = h[1];
        Pop_Heap(1);

        if(DIST[nod] != D[nod]) return 0;

        for(int i = 0; i < G[nod].size(); ++ i)
            if(DIST[ G[nod][i].adj ] == inf || DIST[ G[nod][i].adj ] > DIST[nod] + G[nod][i].cost)
            {
                DIST[ G[nod][i].adj ] = DIST[nod] + G[nod][i].cost;
                if( ! use[ G[nod][i].adj ])
                {
                    use[ G[nod][i].adj ] = 1;
                    Push_Heap(G[nod][i].adj);
                }
                Up_Heap(pos[ G[nod][i].adj]);
            }
    }

    return 1;
}

int main()
{
    int T, S, M, x, y, c;

    fi.open("distante.in");

    fi >> T;

    fo.open("distante.out");

    for(; T -- ; )
    {
        fi >> N >> M >> S;

        for(int i = 1; i <= N; ++ i) fi >> D[i];

        for(; M -- ; )
        {
            fi >> x >> y >> c;
            G[x].push_back(make_conn(y, c));
        }

        if(dij(S)) fo << "DA\n";
        else fo << "NU\n";

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

    fi.close();
    fo.close();

    return 0;
}