Cod sursa(job #2518167)

Utilizator AndreiVisoiuAndrei Visoiu AndreiVisoiu Data 5 ianuarie 2020 10:41:15
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.06 kb
#include <bits/stdc++.h>

using namespace std;

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

typedef pair<int, int> intPair;

const int NMAX = 2000,
          KMAX = 15;

vector<intPair> A[NMAX+1];
priority_queue<intPair, vector<intPair>, greater<intPair>> PQ;
bitset<NMAX+1> viz;

int c[KMAX+1], dZ[NMAX+1], dist[KMAX+1][NMAX+1], R[(1 << KMAX)][KMAX+1],
    N, M, K;


void dijkstra(int X, int d[]) {
    viz.reset();
    PQ.push({0, X});
    for(int i = 1; i <= N; i++)
        d[i] = INT_MAX;
    d[X] = 0;

    while(!PQ.empty()) {
        int U = PQ.top().second;
        PQ.pop();

        if(viz[U]) continue;

        for(const auto& i: A[U]) {
            int V = i.first,
                W = i.second;
            if(d[V] > d[U] + W) {
                d[V] = d[U] + W;
                PQ.push({d[V], V});
            }
        }
        viz[U] = 1;
    }
}

int main()
{
    in >> N >> M >> K;
    for(int i = 1; i <= K; i++)
        in >> c[i];

    int x, y, z;
    while(M--) {
        in >> x >> y >> z;
        A[x].push_back({y, z});
        A[y].push_back({x, z});
    }

    dijkstra(1, dZ);
    if(K == 0)
        out << dZ[N] << '\n';
    else {
        for(int i = 1; i <= K; i++)
            dijkstra(c[i], dist[i]);

        int L = (1 << K) - 1;

        for(int msk = 0; msk <= L; msk++)
            for(int i = 0; i <= K; i++)
                R[msk][i] = (1 << 25);

        for(int msk = 1; msk <= L; msk++)
            for(int i = 1; i <= K; i++)
                if(msk & (1 << (i-1))) {/// localitatea i se afla in submultime
                    int rs = msk - (1 << (i-1)); /// s / {c[i]}
                    if(rs == 0) R[msk][i] = dZ[c[i]]; /// s / {c[i]} = mt vida
                    else for(int j = 1; j <= K; j++)
                        R[msk][i] = min(R[msk][i], R[rs][j] + dist[j][c[i]]);
                }

        int s = INT_MAX;

        for(int i = 1; i <= K; i++)
            s = min(s, R[L][i] + dist[i][N]);

        out << s << '\n';
    }
    return 0;
}