Cod sursa(job #3196593)

Utilizator Allie28Radu Alesia Allie28 Data 24 ianuarie 2024 12:22:37
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.48 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <cmath>
#include <unordered_map>
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

const int LMAX = 2005;
const int INF = 0x3F3F3F3F;
int v[17], newgraph[17][17];
vector<pair<int, int>> L[LMAX];
vector<int> ap(LMAX, -1);
priority_queue<pair<int, int>> Q;

void dijkstra(vector<int> &dist, int source, int i) {
    dist[source] = 0;
    Q.push({0, source});
    while (!Q.empty()) {
        int node = Q.top().second, d = -Q.top().first;
        Q.pop();

        if (d > dist[node]) continue;
        for (pair<int, int> vec : L[node]) {
            if (dist[node] + vec.first < dist[vec.second]) {
                dist[vec.second] = dist[node] + vec.first;
                if (ap[vec.second] == -1) ///daca nodul nu apare in unul dintre cele k noduri
                    Q.push({-dist[vec.second], vec.second});
                else {
                    newgraph[i][ap[vec.second]] = dist[vec.second];
                    newgraph[ap[vec.second]][i] = dist[vec.second];
                }
            }
        }
    }
}

void dijkstra2(vector<int> &dist, int source, int k) {
    Q.push({0, source});
    dist[source] = 0;
    while (!Q.empty()) {
        int node = Q.top().second, d = -Q.top().first;
        Q.pop();
        if (d > dist[node]) continue;
        for (int i = 0; i < k; i++) {
            if (newgraph[node][i] && dist[node] + newgraph[node][i] < dist[i]) {
                dist[i] = dist[node] + newgraph[node][i];
                newgraph[source][i] = dist[i];
                Q.push({-dist[i], i});
            }
        }
    }
}

int main() {
    int n, m, k, i, j;
    fin>>n>>m;
    fin>>k;
    v[0] = 0;
    ap[v[0]] = 0;
    for (i = 1; i <= k; i++) {
        fin>>v[i];
        v[i]--;
        ap[v[i]] = i;
    }
    v[i++] = n - 1;
    ap[n-1] = k + 1;
    k+=2;
    int x, y, c;
    while (m--) {
        fin>>x>>y>>c;
        x--;
        y--;
        L[x].push_back({c, y});
        L[y].push_back({c, x});
    }
    for (i = 0; i < k; i++) {
        vector<int> dist(n, INF);
        dijkstra(dist, v[i], i);
    }
    for (i = 0; i < k; i++) {
        vector<int> dist(k, INF);
        dijkstra2(dist, i, k);
    }
//    for (i = 0; i < k; i++) {
//        fout<<i<<"--";
//        for (j = 0; j < k; j++) {
//            fout<<newgraph[i][j]<<" ";
//        }
//        fout<<endl;
//    }
    ///acum am un graf format numai din nodurile in care vreau sa ajung si muchile dintre ele sunt de distanta minima
    vector<vector<int>> dp((1<<k), vector<int>(k, INF));
    dp[1][0] = 0;//incep din nodul 0
    int mask;
    for (mask = 3; mask < ((1<<k) - 1); mask++) {
        if ((mask&1)) { //daca nodul 0 este in drum
            for (i = 0; (1<<i) <= mask; i++) { //ultimul nod
                if ((mask&(1<<i)) != 0) {
                    for (j = 0; (1<<j) <= mask; j++) {
                        if (i != j && (mask&(1<<j)) != 0 && newgraph[j][i]) {
                            dp[mask][i] = min(dp[mask][i], dp[(mask^(1<<i))][j] + newgraph[j][i]);

                        }
                    }
                }
            }
        }
    }
    for (j = 0; j < k-1; j++) {
        if (newgraph[j][k-1])
            dp[mask][k-1] = min(dp[mask][k-1], dp[(mask^(1<<(k-1)))][j] + newgraph[j][k-1]);
    }
    fout<<dp[mask][k-1];


    fin.close();
    fout.close();
    return 0;
}