Cod sursa(job #2538818)

Utilizator stefan_creastaStefan Creasta stefan_creasta Data 5 februarie 2020 10:27:23
Problema Gather Scor 20
Compilator cpp-64 Status done
Runda simulare_miri Marime 2.69 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[NRMAX];
int b[KMAX];

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 = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                cost[d][i][j] = INF;
            }
        }
        for(int nod = 1; nod <= n; nod++) {
            pq.push({nod, 0});
            cost[d][nod][nod] = 0;
            while(!pq.empty()) {
                auto p = pq.top();
                pq.pop();
                if(cost[d][nod][p.x] == p.c) {
                    for(auto u : vec[p.x]) {
                        if(u.d >= d) {
                            if(cost[d][nod][u.x] > p.c + u.c) {
                                cost[d][nod][u.x] = p.c + (u.c * (d + 1));
                                pq.push({u.x, p.c + u.c});
                            }
                        }
                    }
                }
            }
        }
    }
    for(int mask = 1; mask < (1 << k); mask++) {
        dp[mask] = INF;
    }
    for(int i = 0; i < k; i++) {
        dp[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[mask] + cost[nr1][a[i]][a[j]];
                        dp[mask | (1 << j)] = min(dp[mask | (1 << j)], c);
                    }
                }
            }
        }
    }
    printf("%lld\n", dp[(1 << k) - 1]);
    return 0;
}