Cod sursa(job #606754)

Utilizator SpiderManSimoiu Robert SpiderMan Data 9 august 2011 19:48:26
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.23 kb
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <queue>
# include <vector>
using namespace std;

# define x first
# define y second

const char *FIN = "gather.in", *FOU = "gather.out";
const int MAX_N = 755, MAX_K = 16, oo = 0x3f3f3f3f;

vector < pair < int, pair <int, int> > > G[MAX_N];
priority_queue < pair <int, int> > Q;
int N, M, K, X[MAX_K], D[MAX_K][MAX_K][MAX_N], dp[1 << MAX_K][MAX_K];

inline int p (int X) {
    return 1 << X;
}

inline void dijkstra (int S, int L, int *D) {
    memset (D, 0x3f, sizeof (D[0]) * N), D[S] = 0;
    for (Q.push (make_pair (0, S)); ! Q.empty (); ) {
        pair <int, int> act = Q.top (); Q.pop ();
        if (D[act.y] >= -act.x)
            for (typeof (G[act.y].begin ()) it = G[act.y].begin (); it != G[act.y].end (); ++it) {
                if (it -> y.y >= L && D[it -> x] > D[act.y] + it -> y.x) {
                    D[it -> x] = D[act.y] + it -> y.x;
                    Q.push (make_pair (-D[act.y] - it -> y.x, it -> x));
                }
            }
    }
}

inline void getmin (int &a, int b) {
    a = a < b ? a : b;
}

int main (void) {
    freopen (FIN, "r", stdin);

    scanf ("%d %d %d", &K, &N, &M);
    for (int i = 1, x; i <= K; ++i) {
        scanf ("%d", &x);
        X[i] = --x;
    }
    for (int i = 1, a, b, c, d; i <= M; ++i) {
        scanf ("%d %d %d %d", &a, &b, &c, &d);
        G[--a].push_back (make_pair (--b, make_pair (c, d)));
        G[b].push_back (make_pair (a, make_pair (c, d)));
    }
    for (int i = 0; i <= K + 1; ++i)
        for (int j = 0; j <= K + 1; ++j)
            dijkstra (X[i], j, D[i][j]);
    memset (dp, 0x3f, sizeof (dp));
    dp[1][0] = 0;
    for (int i = 2, cnt, j; i < p(K + 1); ++i) {
        for (cnt = -2, j = i; j; j &= j - 1, ++cnt);
        for (j = 0; j <= K; ++j) {
            if (i & p(j))
                for (int k = 0; k <= K; ++k)
                    if (dp[i - p(j)][k] < oo && D[k][cnt][X[j]] < oo)
                        getmin (dp[i][j], dp[i - p(j)][k] + D[k][cnt][X[j]] * (cnt + 1));
        }
    }
    int sol = dp[p(K + 1) - 1][0];
    for (int i = 0; i <= K; ++i)
        getmin (sol, dp[p(K + 1) - 1][i]);
    fprintf (fopen (FOU, "w"), "%d", sol);
}