Cod sursa(job #3121319)

Utilizator Alex18maiAlex Enache Alex18mai Data 11 aprilie 2023 19:50:41
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.15 kb
#include <fstream>
#include <vector>
#include <queue>
#include <map>

using namespace std;

// ifstream cin("input"); ofstream cout("output");
ifstream cin("ubuntzei.in"); ofstream cout("ubuntzei.out");

const int inf = 2e9;

int n, m, k;

vector<int> prieten;
vector<vector<pair<int,int>>> gr;

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> Q;
vector<int> distanta;

vector<vector<int>> min_dist;
vector<vector<int>> dp;

void read() {
    cin >> n >> m;
    gr.resize(n + 1);
    distanta.resize(n+1);

    cin >> k;
    prieten.resize(k+1);
    min_dist.resize(k+2, vector<int>(k+2, inf));
    dp.resize((1 << k), vector<int>(k+1));

    for (int i = 1; i <= k; i++) {
        cin >> prieten[i];
    }

    for (int i = 1; i <= m; i++) {
        int a, b, val;
        cin >> a >> b >> val;
        gr[a].push_back({b, val});
        gr[b].push_back({a, val});
    }
}

void dijkstra(int root, bool nu_am_prieteni = false) {
    for (int i = 1; i <= n; i++) {
        distanta[i] = inf;
    }

    if (nu_am_prieteni){
        Q.push({1, 0});
        distanta[1] = 0;
    }
    else{
        Q.push({prieten[root], 0});
        distanta[prieten[root]] = 0;
    }

    while (!Q.empty()) {
        pair<int, int> now = Q.top();
        Q.pop();
        if (distanta[now.first] != now.second) {
            continue;
        }
        for (auto &x : gr[now.first]) {
            if (distanta[x.first] > now.second + x.second) {
                distanta[x.first] = now.second + x.second;
                Q.push({x.first, distanta[x.first]});
            }
        }
    }

    min_dist[root][0] = distanta[1];
    min_dist[root][k + 1] = distanta[n];
    for (int i = 1; i <= k; i++) {
        min_dist[root][i] = distanta[prieten[i]];
    }
}


void solve() {
    if (k == 0) {
        dijkstra(1, true);
        cout << distanta[n];
        return;
    }

    for (int i = 1; i <= k; i++) {
        dijkstra(i);
    }

    for (int mask = 0; mask < (1 << k); mask++) {
        for (int last = 0; last < k; last++) {
            dp[mask][last] = inf;
        }
    }

    dp[0][0] = 0;

    for (int mask = 0; mask < (1 << k); mask++) {
        for (int last = 0; last < k; last++) {
            if (dp[mask][last] == inf) {
                continue;
            }
            for (int bit = 0; bit < k; bit++) {
                if ((1 << bit) & mask) {
                    continue;
                }
                if (mask == 0) {
                    if (min_dist[bit + 1][0] != inf) {
                        dp[mask ^ (1 << bit)][bit] = min(dp[mask ^ (1 << bit)][bit], min_dist[bit + 1][0]);
                    }
                    continue;
                }
                if (min_dist[last + 1][bit + 1] != inf) {
                    dp[mask ^ (1 << bit)][bit] = min(dp[mask ^ (1 << bit)][bit],
                                                     dp[mask][last] + min_dist[last + 1][bit + 1]);
                }
            }
        }
    }

    int ans = inf;

    for (int i = 0; i < k; i++) {
        if (min_dist[i + 1][k + 1] != 0) {
            ans = min(ans, dp[(1 << k) - 1][i] + min_dist[i + 1][k + 1]);
        }
    }

    cout << ans;
}

int main() {
    read();
    solve();
}