Cod sursa(job #2990894)

Utilizator DooMeDCristian Alexutan DooMeD Data 8 martie 2023 18:58:59
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.33 kb
#include <bits/stdc++.h>
using namespace std;
const int nmax = 2e3;
const int kmax = 15;
const int inf = 2e9 + 5;

vector<vector<pair<int, int>>> dx(nmax+5);
int n, m, k, v[kmax+5], dist[nmax+5][nmax+5], temp[nmax+5];

int dp[(1<<kmax)][kmax];
// dp[mask][i] - went through all nodes in mask and are in node i

void dijkstra(int start) {
    priority_queue< pair<int, int>,
                    vector<pair<int, int>>,
                    greater<pair<int, int>>> pq;
    for(int i=1; i<=n; i++) temp[i] = inf;
    temp[start] = 0;
    pq.emplace(0, start);
    while(pq.empty() == false) {
        pair<int, int> now = pq.top(); pq.pop();
        if(temp[now.second] != now.first) continue;

        for(auto edge : dx[now.second]) 
            if(temp[edge.second] > temp[now.second] + edge.first) {
                temp[edge.second] = temp[now.second] + edge.first;
                pq.emplace(temp[edge.second], edge.second);
            }
    }
    for(int i=1; i<=n; i++) {
        dist[start][i] = min(dist[start][i], temp[i]);
        dist[i][start] = min(dist[i][start], temp[i]);
    }
}

int main() {
    ifstream f("ubuntzei.in");
    ofstream g("ubuntzei.out");

    f >> n >> m >> k;
    for(int i=0; i<k; i++) f >> v[i];
    for(int i=1; i<=m; i++) {
        int x, y, d; f >> x >> y >> d;
        dx[x].emplace_back(d, y);
        dx[y].emplace_back(d, x);
    }
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            dist[i][j] = inf;

    dijkstra(1); dijkstra(n);
    for(int i=0; i<k; i++) dijkstra(v[i]);

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

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

    for(int mask=0; mask<(1<<k); mask++)
        for(int node=0; node<k; node++) {
            if(((1<<node) & mask) == 0) continue;
            
            for(int next=0; next<k; next++) {
                if(next == node or ((1<<next) & mask)) continue;
                
                int newmask = mask + (1<<next);
                int cost = dist[v[node]][v[next]];
                dp[newmask][next] = min(dp[newmask][next], dp[mask][node] + cost);
            }
        }

    if(k == 0) {
        g << dist[1][n];
        return 0;
    }

    int ans = inf;
    for(int i=0; i<k; i++) ans = min(ans, dp[(1<<k)-1][i] + dist[v[i]][n]);
    g << ans;
    return 0;
}