Cod sursa(job #2932605)

Utilizator cyg_dawidDavid Ghiberdic cyg_dawid Data 3 noiembrie 2022 12:00:40
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.72 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

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

int const nmax = 2000;
int const kmax = 15;
int const INF = 1e9;
int c[kmax + 5];

std::vector<std::pair<int, int>> G[nmax + 5];
int dist[kmax + 5][nmax + 5];

// -dist index
std::priority_queue<std::pair <int, int>> pq;

int dp[(1 << kmax) + 5][kmax + 5];

int main() {
    int n, m;
    fin >> n >> m;
    int k;
    fin >> k;
    for (int i = 1; i <= k; i++)
        fin >> c[i];

    for (int i = 1; i <= m; i++) {
        int x, y, z;
        fin >> x >> y >> z;
        G[x].push_back({y, z});
        G[y].push_back({x, z});
    }

    if (k == 0) {
        for (int i = 1; i <= n; i++)
            dist[1][i] = INF;
        dist[1][1] = 0;
        pq.push({0, 1});
        while (!pq.empty()) {
            auto top = pq.top();
            pq.pop();
            top.first = -top.first;
            for (auto x: G[top.second]) {
                if (top.first + x.second < dist[1][x.first]) {
                    dist[1][x.first] = top.first + x.second;
                    pq.push({-dist[1][x.first], x.first});
                }
            }
        }
        fout << dist[1][n];
        return 0;
    }

    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= n; j++)
            dist[i][j] = INF;
        dist[i][c[i]] = 0;
    }
    for (int index = 1; index <= k; index++) {
        pq.push({0, c[index]});
        while (!pq.empty()) {
            auto top = pq.top();
            pq.pop();
            top.first = -top.first;
            for (auto x : G[top.second]) {
                if (top.first + x.second < dist[index][x.first]) {
                    dist[index][x.first] = top.first + x.second;
                    pq.push({-dist[index][x.first], x.first});
                }
            }
        }
    }
    for (int state = 0; state < (1 << k); state++)
        for (int i = 0; i < k; i++)
            dp[state][i] = INF;
    for (int i = 0; i < k; i++) {
        dp[0][i] = 0;
        dp[(1 << i)][i] = dist[i + 1][1];
    }

    for (int state = 0; state < (1 << k); state++) {
        for (int last = 0; last < k; last++) {
            if (state & (1 << last)) {
                for (int j = 0; j < k; j++) {
                    if ((state & (1 << j)) == 0) {
                        dp[state | (1 << j)][j] = std::min(dp[state | (1 << j)][j],
                                                           dp[state][last] + dist[last + 1][c[j + 1]]);
                    }
                }
            }
        }
    }

    int ans = INF;
    for (int i = 0; i < k; i++)
        ans = std::min(ans,
                       dp[(1 << k) - 1][i] + dist[i + 1][n]);
    fout << ans << "\n";
    return 0;
}