Cod sursa(job #3341208)

Utilizator NeamtuMateiNeamtu Matei-Constantin NeamtuMatei Data 18 februarie 2026 14:18:19
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.06 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <map>
using namespace std;

#define in fin
#define out fout
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

typedef pair<int, int> pii;
const int MAXN = 2e3;
const int MAXM = 1e4;
const int MAXK = 17; // hmm
const int INF = 1e9;

int n, m, kc, cx, x, y, z, dmin;
int orase[MAXK+1];
int st[MAXN+1];
int dp[1 << MAXK][MAXK+1]; // dp[mask][i] = distanta minima pana in nodul oras[i] vizitand nodurile cu biti 1 din masca

vector<pii> graf[MAXN+1];
vector<vector<int>> distante(MAXN+2, vector<int>(MAXN+2, INF));

void citire();

void dijkstra(int init, vector<int> &dist) {
    priority_queue<pii, vector<pii>, greater<pii>> pq;

    dist[init] = 0;
    pq.push({ 0, init });

    while (!pq.empty()) {
        int nod = pq.top().second;
        int distInit = pq.top().first;
        pq.pop();

        if (distInit > dist[nod])
            continue;

        for (auto e: graf[nod]) {
            int nodExt = e.first;
            int cost = e.second;

            if (dist[nodExt] > dist[nod] + cost) {
                dist[nodExt] = dist[nod] + cost;
                pq.push({ dist[nodExt], nodExt });
            }
        }
    }
}

int main() {
    citire();

    dijkstra(1, distante[1]);
    for (int i = 1; i <= kc; i++)
        dijkstra(orase[i], distante[ orase[i] ]);

    orase[0] = 1;
    orase[kc + 1] = n;

    int max_mask = 1 << kc;

    // distantele se initializeaza cu INF
    for (int mask = 0; mask < max_mask; mask++)
        for (int j = 0; j <= kc + 1; j++)
            dp[mask][j] = INF;

    dp[0][0] = 0; // base case; din orase[0] nu am parcurs niciun oras
    for (int mask = 0; mask < max_mask; mask++) {
        for (int nod = 0; nod <= kc; nod++) {

            // incercam sa vizitam unul dintre orasele necesare
            for (int e = 1; e <= kc; e++) {
                int bit = e - 1;

                // verificam daca nu l-am vizitat deja in masca
                if ( (mask & (1 << bit)) == 0 ) {
                    long long dist = dp[mask][nod] + distante[ orase[nod] ][ orase[e] ];
                    int maskadd = mask | (1 << bit);

                    if (dp[maskadd][e] > dist)
                        dp[maskadd][e] = dist;
                }
            }

            // sau mergem direct la ultimul oras N
            long long distN = dp[mask][nod] + distante[ orase[nod] ][ orase[kc + 1] ];
            if (dp[mask][kc + 1] > distN)
                dp[mask][kc + 1] = distN;
        }
    }

    // rezultatul pe care il cautam este basically dp[masca_full_biti_1][n],
    // intrucat vrem sa fi trecut prin toate orasele necesare (toti bitii din masca trb sa fie 1)
    out << dp[max_mask - 1][kc + 1];

    return 0;
}


void citire() {
    in >> n >> m >> kc;
    for (int i = 1; i <= kc; i++)
        in >> orase[i];

    for (int i = 1; i <= m; i++) {
        in >> x >> y >> z;

        graf[x].push_back({y, z});
        graf[y].push_back({x, z});
    }
}