Cod sursa(job #2532220)

Utilizator vxpsnVictor Pusnei vxpsn Data 27 ianuarie 2020 16:21:54
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.64 kb
#pragma GCC optimize ("O2")

#include <fstream>
#include <vector>
#include <queue>

using namespace std;

ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

const int MAXN = 2001;
const int MAXK = 17;
const int MAXS = (1 << 15);

int n, m, k, fr[MAXN], predist[MAXK][MAXK], dp[MAXK][MAXS], d[MAXN], sol = 1e9;
vector<pair<int, int>> g[MAXN];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;

int distance(int A, int B) {
    fill(d, &d[MAXN], 1e9);
    d[A] = 0;
    pq.push({0, A});
    while(!pq.empty()) {
        while(!pq.empty() && pq.top().first > d[pq.top().second])
            pq.pop();
        if(pq.empty()) break;
        int node = pq.top().second;
        pq.pop();
        for(auto i : g[node])
            if(d[i.first] > d[node] + i.second) {
                d[i.first] = d[node] + i.second;
                pq.push({d[i.first], i.first});
            }
    }
    return d[B];
}

void dijkstra(int A, int i) {
    fill(d, &d[MAXN], 1e9);
    d[A] = 0;
    pq.push({0, A});
    while(!pq.empty()) {
        while(!pq.empty() && pq.top().first > d[pq.top().second])
            pq.pop();
        if(pq.empty()) break;
        int node = pq.top().second;
        pq.pop();
        for(auto i : g[node])
            if(d[i.first] > d[node] + i.second) {
                d[i.first] = d[node] + i.second;
                pq.push({d[i.first], i.first});
            }
    }
    for(int j = 0; j <= k + 1; ++j)
        if(i != j)
            predist[i][j] = predist[j][i] = d[fr[j]];
}

int main() {
    ios::sync_with_stdio(0);
    fin.tie(0);
    fout.tie(0);

    fin >> n >> m >> k;
    for(int i = 1; i <= k; ++i) fin >> fr[i];
    for(int i = 1, x, y, w; i <= m; ++i) {
        fin >> x >> y >> w;
        g[x].push_back({y, w});
        g[y].push_back({x, w});
    }

    if(k == 0) {
        fout << distance(1, n);
        return 0;
    }

    fr[0] = 1;
    fr[k + 1] = n;

    for(int i = 1; i <= k; ++i)
        dijkstra(fr[i], i);

    for(int i = 0; i < k; ++i)
        dp[i + 1][1 << i] = predist[0][i + 1];

    for(int i = 1; i < (1 << k); ++i)
        for(int x = 0; x < k; ++x)
            if(i & (1 << x))
                for(int j = 0; j < k; ++j)
                    if(i & (1 << j) && x != j) {
                        if(dp[j + 1][i] == 0) dp[j + 1][i] = 1e9;
                        dp[j + 1][i] = min(dp[j + 1][i], dp[x + 1][i ^ (1 << j)] + predist[x + 1][j + 1]);
                    }

    for(int i = 1; i <= k; ++i)
        sol = min(sol, dp[i][(1 << k) - 1] + predist[i][k + 1]);

    fout << sol;

    return 0;
}