Cod sursa(job #1601812)

Utilizator algebristulFilip Berila algebristul Data 16 februarie 2016 11:38:11
Problema Gather Scor 0
Compilator cpp Status done
Runda contest_3 Marime 2.13 kb
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int nmax = 752;

bool InQ[nmax][32768];
long long D[nmax][32768];
int nodes[nmax];
int idx[nmax];
int k, n, m;
vector<int> A[nmax];
vector<int> C[nmax];
vector<int> L[nmax];

int numbits(int x) {
    int y = 0;
    while (x) {
        y++;
        x = x & (x-1);
    }

    return y;
}

void dp() {
    memset(D, 0x3f3f3f3f, sizeof(D));
    D[1][0] = 0;
    InQ[1][0] = 1;

    queue<pair<int, int> > Q;

    Q.push({1, 0});

    while (!Q.empty()) {
        int x = Q.front().first,
            m = Q.front().second;

        Q.pop();
        InQ[x][m] = 0;

        if (idx[x] != -1) {
            if (D[x][m | (1 << idx[x])] > D[x][m]) {
                D[x][m | (1 << idx[x])] = D[x][m];
                if (!InQ[x][m | (1 << idx[x])]) {
                    InQ[x][m | (1 << idx[x])] = 1;
                    Q.push({x, m | (1 << idx[x])});
                }
            }
        }

        for (int i = 0; i < A[x].size(); i++) {
            int y = A[x][i];
            int c = C[x][i];
            int l = L[x][i];

            if (numbits(m) <= l) {
                if (D[y][m] > D[x][m] + c * (numbits(m) + 1)) {
                    if (!InQ[y][m]) {
                        Q.push({y, m});
                        InQ[y][m] = 1;
                    }
                    D[y][m] = D[x][m] + c * (numbits(m) + 1);
                }
            }
        }
    }
}

int main() {
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);

    scanf("%d %d %d", &k, &n, &m);

    for (int i = 1; i <= n; i++) idx[i] = -1;

    for (int i = 0; i < k; i++) {
        scanf("%d", &nodes[i]);
        idx[nodes[i]] = i;
    }

    for (int i = 1, a, b, c, d; i <= m; i++) {
        scanf("%d %d %d %d", &a, &b, &c, &d);

        A[a].push_back(b);
        A[b].push_back(a);

        C[a].push_back(c);
        C[b].push_back(c);

        L[a].push_back(d);
        L[b].push_back(d);
    }

    dp();

    long long ans = 0x3f3f3f3f3f3f3f3fLL;
    for (int i = 1; i <= n; i++) {
        ans = min(ans, D[i][(1<<k)-1]);
    }

    printf("%lld\n", ans);

    return 0;
}