Cod sursa(job #10661)

Utilizator sandyxpSanduleac Dan sandyxp Data 28 ianuarie 2007 22:30:09
Problema Amenzi Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.11 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define FIN "amenzi.in"
#define FOUT "amenzi.out"
#define MAXN 151
#define MAXK 12000 // nr de "conditii" de amenzi
#define MAXP 8000  // locatii posibile de final
#define MAXTime 3501
#define ul unsigned long
#define INF 0x3f3f3f3f

/* Liste de adiacenta */
typedef struct item *point;
struct item { int y, c; item *r; };
point L[MAXN];

typedef ul graf[MAXN][MAXN];
struct ts { int t, x; } Fin[MAXP];
struct amenda { int t, x, c; } Amenzi[MAXK];
/* Vector dinamica */
int A[MAXTime][MAXN];

graf G;
int N, M, K, P;

void debug() 
{
    int i, j;
    for (i=1; i<=N; ++i) {
        for (j=1;j<=N; ++j)
            printf("%3lu ", G[i][j]);
        printf("\n");
    }
}

inline bool Compar(const amenda &A, const amenda &B)
{
    // fields: t, x, c
    return (A.t < B.t ||
        (A.t == B.t && 
            (A.x < B.x ||
             A.x == B.x && A.c < B.c
            )
        )
       );
}

inline void rf(graf &G)
{
    int i, j, k;

    for (k=1; k<=N; ++k)
        for (i=1; i<=N; ++i)
            for (j=1; j<=N; ++j)
                if (G[i][j] > G[i][k] + G[k][j])
                    G[i][j] = G[i][k] + G[k][j];
}

void rez() 
{
    int i, j, crt = 0;
    
    //rf(G);
    sort(Amenzi, Amenzi + K, Compar);
    memset(A, 0xFF, sizeof(A));
    A[0][1] = 0;
    
    for (i=0; i<=MAXTime; ++i)
        for (j=1; j<=N; ++j)
            if (A[i][j] != -1) {
                // crt = "amenda" curenta
                // iau si updatez toate nodurile in care pot ajunge..
                for (; crt < K && Amenzi[crt].t < i ||
                     Amenzi[crt].t == i && Amenzi[crt].x < j; ++crt);
                while (crt < K && Amenzi[crt].t == i && Amenzi[crt].x == j)
                    A[i][j] += Amenzi[crt++].c;
                if (i+1<MAXTime && A[i+1][j] < A[i][j])
                    A[i+1][j] = A[i][j];

                if (! (i && A[i-1][j] == A[i][j]))
                    for (point p = L[j]; p; p = p->r)
                        if (p->c+i < MAXTime && A[p->c+i][p->y] < A[i][j])
                            A[p->c+i][p->y] = A[i][j];
            }
    /*
    for (i=0; i<=50; ++i) {
        printf("%2d: ", i);
        for (j=1; j<=N; ++j)
           printf("%5d ", A[i][j]);
        printf("\n");
    }
    */
    for (i=0; i<P; ++i)
        printf("%d\n", A[ Fin[i].t ][ Fin[i].x ]);
}



void add_edge(int a, int b, int c)
{
    point temp = new item;
    temp->y = b; temp->c = c;
    temp->r = L[a];
    L[a] = temp;
}

void citire() 
{
    int i, x, y, c;
    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);
    scanf("%d %d %d %d", &N, &M, &K, &P);
    memset(G, INF, sizeof(G));
    for (i=0; i<M; ++i)
    {
        scanf("%d %d %d", &x, &y, &c);
        add_edge(x, y, c);  add_edge(y, x, c);
        G[x][y] = c; G[y][x] = c;
    }
    for (i=0; i<K; ++i)
    {
        scanf("%d %d %d", &x, &y, &c); // nod x, timp y, amenda c
        Amenzi[i].x = x; Amenzi[i].t = y; Amenzi[i].c = c;
    }
    for (i=0; i<P; ++i) 
    {
        scanf("%d %d", &x, &y);
        Fin[i].x = x; Fin[i].t = y;
    }
}

int main()
{
    citire();
    rez();
    return 0;
}