Cod sursa(job #2923843)

Utilizator cyg_dawidDavid Ghiberdic cyg_dawid Data 19 septembrie 2022 21:27:43
Problema Ubuntzei Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.21 kb
#include <fstream>
#include <vector>
#include <queue>

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

int const nmax = 2000;
int const mmax = 10000;
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});
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= n; j++)
            dist[c[i]][j] = INF;
        dist[c[i]][i] = 0;
    }
    for (int index = 1; index <= k; index++) {
        int start = c[index];
        pq.push({0, start});
        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[c[index]][x.second]) {
                    dist[c[index]][x.second] = top.first + x.second;
                    pq.push({-dist[c[index]][x.second], x.second});
                }
            }
        }
    }
    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[c[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[c[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[c[i + 1]][n]);
    fout << ans << "\n";
    return 0;
}