Cod sursa(job #2539100)

Utilizator stefan_creastaStefan Creasta stefan_creasta Data 5 februarie 2020 17:03:54
Problema Gather Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const long long INF = 10000000000000000;
const int NRMAX = 1 << 17;
const int NMAX = 755;
const int KMAX = 18;
long long cost[KMAX][NMAX][NMAX];
int a[NMAX];
struct Muchie {
    int x;
    long long c;
    int d;
};
vector <Muchie> vec[NMAX];
struct Dikjstra {
    int x;
    long long c;
};
bool operator < (Dikjstra first, Dikjstra second) {
    return (first.c < second.c);
}
priority_queue <Dikjstra> pq;
long long dp[KMAX][NRMAX];
int b[KMAX];
void F(int nod, int d) {
    pq.push({nod, 0});
    while(!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        if(cost[d][nod][p.x] == INF) {
            cost[d][nod][p.x] = p.c;
            for(auto u : vec[p.x]) {
                if(u.d >= d) {
                    if(cost[d][nod][u.x] == INF) {
                        pq.push({u.x, p.c + (u.c * (d + 1))});
                    }
                }
            }
        }
    }
}

int main() {
    int k, n, m;
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);
    scanf("%d%d%d", &k, &n, &m);
    for(int i = 0; i < k; i++) {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= m; i++) {
        int x, y, d;
        long long c;
        scanf("%d%d%lld%d", &x, &y, &c, &d);
        vec[x].push_back({y, c, d});
        vec[y].push_back({x, c, d});
    }
    for(int d = 0; d <= k; d++) {
        for(int i = 0; i < k; i++) {
            for(int j = 1; j <= n; j++) {
                cost[d][a[i]][j] = INF;
            }
        }
        for(int j = 1; j <= n; j++) {
            cost[d][1][j] = INF;
        }
        F(1, d);
        for(int i = 0; d > 0 && i < k; i++) {
            F(a[i], d);
        }
    }
    for(int mask = 1; mask < (1 << k); mask++) {
        for(int j = 0; j <= k; j++) {
            dp[j][mask] = INF;
        }
    }
    for(int i = 0; i < k; i++) {
        dp[i][1 << i] = cost[0][1][a[i]];
    }
    for(int mask = 1; mask < (1 << k) - 1; mask++) {
        int cmask = mask, top = 0;
        while(mask > 0) {
            b[top++] = mask % 2;
            mask /= 2;
        }
        mask = cmask;
        int nr1 = 0;
        for(int i = 0; i < top; i++) {
            nr1 += b[i];
        }
        for(int i = 0; i < top; i++) {
            if(b[i] == 1) {
                for(int j = 0; j < k; j++) {
                    if(b[j] == 0) {
                        long long c = dp[i][mask] + cost[nr1][a[i]][a[j]];
                        dp[j][mask | (1 << j)] = min(dp[j][mask | (1 << j)], c);
                    }
                }
            }
        }
    }
    long long sol = INF;
    for(int i = 0; i < k; i++) {
        sol = min(sol, dp[i][(1 << k) - 1]);
    }
    printf("%lld\n", sol);
    return 0;
}