Cod sursa(job #2246353)

Utilizator IulianOleniucIulian Oleniuc IulianOleniuc Data 26 septembrie 2018 23:28:35
Problema Ubuntzei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <queue>
#include <vector>
#include <climits>
#include <fstream>
#include <algorithm>

#define KMAX 15
#define NMAX 2010

using std::sort;
using std::vector;
using std::priority_queue;

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

struct Arc {
    int node;
    int cost;
};

inline bool operator<(Arc x, Arc y) {
    return x.cost > y.cost;
}

int n, m, k;
int c[KMAX];
vector<Arc> ad[NMAX];

vector<int> conf;
int dij[NMAX][NMAX];
int dp[KMAX][1 << KMAX];

bool onPQ[NMAX];
priority_queue<Arc> pq;

void dijkstra(int start) {
    pq.push({start, 0});
    onPQ[start] = true;

    while (!pq.empty()) {
        int node = pq.top().node;
        pq.pop();
        onPQ[node] = false;

        for (Arc arc : ad[node])
            if (!dij[start][arc.node] || dij[start][node] + arc.cost < dij[start][arc.node]) {
                dij[start][arc.node] = dij[start][node] + arc.cost;
                if (!onPQ[arc.node]) {
                    pq.push({arc.node, dij[start][arc.node]});
                    onPQ[arc.node] = true;
                }
            }
    }
}

int nrBits(int n) {
    int ret = 0;
    if (n)
        do
            ret++;
        while (n &= (n - 1));
    return ret;
}

bool cmp(int x, int y) {
    return nrBits(x) < nrBits(y);
}

inline int min(int x, int y) {
    return x < y ? x : y;
}

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

    int x, y, z;
    for (int i = 0; i < m; i++) {
        fin >> x >> y >> z;
        ad[x].push_back({y, z});
        ad[y].push_back({x, z});
    }

    for (int i = 0; i < k; i++)
        dijkstra(c[i]);

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

    for (int i = 2; i < (1 << k); i++)
        if (i & (i - 1))
            conf.push_back(i);
    sort(conf.begin(), conf.end(), cmp);

    for (int mult : conf)
        for (int i = 0; i < k; i++)
            if (mult & (1 << i)) {
                dp[i][mult] = INT_MAX;

                int subm = mult - (1 << i);
                for (int j = 0; j < k; j++)
                    if (subm & (1 << j))
                        dp[i][mult] = min(dp[i][mult], dp[j][subm] + dij[c[i]][c[j]]);
            }

    int sol = INT_MAX;
    for (int i = 0; i < k; i++)
        sol = min(sol, dp[i][(1 << k) - 1] + dij[c[i]][n]);

    fout << sol << '\n';
    fout.close();
    return 0;
}