Cod sursa(job #1522528)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 11 noiembrie 2015 19:48:04
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.85 kb
#include <cstdio>
#include <queue>
#include <algorithm>

using std::min;

const int MAX_K = 15 + 1;
const int MAX_N = 750;
const int MAX_M = 1250;
const int NIL = -1;
const long long INF = 100000000000000LL;

struct Edge {
    int v, next;
    long long cost, cap;
};

/* datele citite */
Edge l[2 * MAX_M];
int adj[MAX_N];
int p[MAX_K];
int n;

/* pentru SPFA */
long long d[MAX_N];
bool inQueue[MAX_N];
std::queue <int> q;

/* pentru Hamilton */
long long DP[MAX_K][MAX_K][MAX_N];
long long popCount[1 << MAX_K];
long long H[1 << MAX_K][MAX_K];
int k;

void addEdge(int u, int v, long long cost, long long capacity, int pos) {
    l[pos].v = v;
    l[pos].cost = cost;
    l[pos].cap = capacity;
    l[pos].next = adj[u];
    adj[u] = pos;
}

void spfa(int u, long long minCap) {
    for (int i = 0; i < n; i++) {
        d[i] = INF;
    }
    q.push(u);
    d[u] = 0;
    while (!q.empty()) {
        u = q.front();
        q.pop();
        inQueue[u] = 0;
        for (int i = adj[u]; i != NIL; i = l[i].next) {
            if (l[i].cap >= minCap) {
                int v = l[i].v;
                long long cost = d[u] + l[i].cost;
                if (d[v] > cost) {
                    d[v] = cost;
                    if (!inQueue[v]) {
                        inQueue[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
    }
}

long long go(int mask, long long node) {
    if (H[mask][node]) {
        return H[mask][node];
    }
    long long q = INF;
    if (mask == (1 << k) - 1) {
        q = 0;
    } else {
        for (int i = 0; i < k; i++) {
            if (!((mask >> i) & 1)) {
                q = min(q, go(mask ^ (1 << i), i) + popCount[mask] * DP[node][ popCount[mask] ][ p[i] ]);
            }
        }
    }
    return H[mask][node] = q;
}

int main(void) {
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);
    int m;
    int u, v;
    long long cost, capacity;

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

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

    for (int i = 0; i < n; i++) {
        adj[i] = NIL;
    }
    for (int i = 0; i < m; i++) {
        scanf("%d%d%lld%lld", &u, &v, &cost, &capacity);
        addEdge(u - 1, v - 1, cost, capacity + 1, 2 * i);
        addEdge(v - 1, u - 1, cost, capacity + 1, 2 * i + 1);
    }
    fclose(stdin);

    for (int i = 0; i < k; i++) {
        for (int j = 1; j < k; j++) {
            spfa(p[i], j);
            for (u = 0; u < n; u++) {
                DP[i][j][u] = d[u];
            }
        }
    }

    for (int i = 1; i < (1 << k); i++) {
        popCount[i] = (i & 1) + popCount[i >> 1];
    }

    printf("%lld\n", go(1, 0));
    fclose(stdout);

    return 0;
}