Cod sursa(job #1624221)

Utilizator andreiiiiPopa Andrei andreiiii Data 2 martie 2016 09:28:24
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.35 kb
#include <algorithm>
#include <fstream>
#include <cstring>
#include <queue>

using namespace std;

const int NMAX = 2005, KMAX = 15, INF = 0x3f3f3f3f;

vector<pair<int, int>> G[NMAX];
int dist[NMAX];
int gr[KMAX][KMAX];

int dinit[KMAX], dend[KMAX];

int cnodes[KMAX];

int dp[1 << KMAX][KMAX];

void dijkstra(int node) {
    memset(dist, INF, sizeof(dist));
    dist[node] = 0;
    priority_queue<pair<int, int>> q;
    q.push(make_pair(0, node));
    while (!q.empty()) {
        int node = q.top().second, cost = -q.top().first;
        q.pop();

        if (cost > dist[node]) continue;

        for (const auto& p: G[node]) {
            if (dist[p.first] > cost + p.second) {
                dist[p.first] = cost + p.second;
                q.push(make_pair(-dist[p.first], p.first));
            }
        }
    }
}

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

    int n, m;
    fin >> n >> m;

    int k;
    fin >> k;
    for (int i = 0; i < k; ++i) {
        fin >> cnodes[i];
    }

    while (m-- > 0) {
        int x, y, c;
        fin >> x >> y >> c;

        G[x].push_back(make_pair(y, c));
        G[y].push_back(make_pair(x, c));
    }

    for (int i = 0; i < k; ++i) {
        dijkstra(cnodes[i]);
        for (int j = 0; j < k; ++j) {
            gr[i][j] = dist[cnodes[j]];
        }
    }

    dijkstra(1);
    for (int i = 0; i < k; ++i) {
        dinit[i] = dist[cnodes[i]];
    }

    if (k == 0) {
        fout << dist[n] << '\n';
        return 0;
    }

    dijkstra(n);
    for (int i = 0; i < k; ++i) {
        dend[i] = dist[cnodes[i]];
    }

    memset(dp, INF, sizeof dp);
    for (int i = 0; i < k; ++i) {
        dp[1 << i][i] = dinit[i];
    }

    for (int conf = 1; conf < (1 << k); ++conf) {
        for (int i = 0; i < k; ++i) {
            if (dp[conf][i] == INF) continue;
            for (int j = 0; j < k; ++j) {
                if (!(conf & (1 << j))) {
                    int nconf = conf | (1 << j);
                    dp[nconf][j] = min(dp[nconf][j], dp[conf][i] + gr[i][j]);
                }
            }
        }
    }

    int ans = INF;
    for (int i = 0; i < k; ++i) {
        ans = min(ans, dp[(1 << k) - 1][i] + dend[i]);
    }

    fout << ans << '\n';

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