Cod sursa(job #2524106)

Utilizator ioana_marinescuMarinescu Ioana ioana_marinescu Data 15 ianuarie 2020 09:08:32
Problema Ubuntzei Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.13 kb
#include <bits/stdc++.h>

const int MAX_N = 2000;
const int MAX_K = 15;
const int INF = 1e9;

using namespace std;

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

struct Node {
    int v, cost;

    bool operator < (const Node &other) const {
        return this-> cost > other.cost;
    }
};

int n, m, k;
int ubu[MAX_K + 5];
int dist[MAX_N + 5];
int adj[MAX_K + 5][MAX_K + 5];
int dp[MAX_K + 5][1 << MAX_K + 5];

vector<Node> G[MAX_N + 5];

void dijkstra() {
    priority_queue<Node> pq;

    for (int i = 0; i <= k + 1; i++) {
        //memset(dist, INF, sizeof dist);
        for (int d = 0; d <= MAX_N + 3; d++)
            dist[d] = INF;

        dist[ubu[i]] = 0;
        pq.push({ubu[i], 0});
        while (!pq.empty()) {
            Node u = pq.top();
            pq.pop();

            if (u.cost != dist[u.v])
                continue;

            for (Node v : G[u.v])
                if (dist[v.v] > dist[u.v] + v.cost) {
                    dist[v.v] = dist[u.v] + v.cost;
                    pq.push({v.v, dist[v.v]});
                }
        }

        for (int j = 0; j <= k + 1; j++)
            adj[i][j] = dist[ubu[j]];
    }
}

int main() {
    fin >> n >> m >> k;
    for (int i = 0; i < k; i++)
        fin >> ubu[i];

    for (int i = 0; i < m; i++) {
        int a, b, c;
        fin >> a >> b >> c;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }

    ubu[k] = 1;
    ubu[k + 1] = n;

    dijkstra();

    //memset(dp, INF, sizeof dp);
    for (int i = 0; i < MAX_K + 3; i++)
        for (int j = 0; j <= (1 << MAX_K); j++)
            dp[i][j] = INF;

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

    for (int mask = 1; mask < (1 << k); mask++)
      for (int u = 0; u < k; u++)
        if ((1 << u) & mask)
          for (int v = 0; v < k; v++)
            if (v != u && ((1 << v) & mask))
              dp[u][mask] = min(dp[u][mask], dp[v][mask] + dp[v][mask ^ (1 << u)] + adj[v][u]);

    int ans = INF;

    for (int i = 0; i < k; i++)
        ans = min(ans, dp[i][(1 << k) - 1] + adj[i][k + 1]);

    if (k == 0)
        ans = adj[k][k + 1];
    fout << ans << '\n';
    return 0;
}