Cod sursa(job #1876452)

Utilizator RobybrasovRobert Hangu Robybrasov Data 12 februarie 2017 13:19:48
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.5 kb
#include <fstream>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <bitset>
#define N 2001
#define K 16
#define iter vector<pair<int, int> >::iterator
#define val first
#define cost second
#define INF 0x3f3f3f3f

using namespace std;

vector<pair<int, int> > L[N];
int C[N], O[K];
int D[K][N], R[1 << (K - 1)][K];
struct Comp {
    bool operator()(int a, int b) {
        return C[a] > C[b];
    }
};
priority_queue<int, vector<int>, Comp> Q;

void dijkstra(int pos, int n) {
    bitset<N> E;
    int node = O[pos];
    for (int i = 1; i <= n; ++i)
        C[i] = INF;
    C[node] = 0;
    for (Q.push(node); !Q.empty(); Q.pop()) {
        int head = Q.top();
        E[head] = 0;
        for (iter it = L[head].begin(); it != L[head].end(); ++it) {
            int nc = C[head] + it -> cost;
            if (nc < C[it -> val]) {
                C[it -> val] = nc;
                if (!E[it -> val]) {
                    Q.push(it -> val);
                    E[it -> val] = 1;
                }
            }
        }
    }
    for (int j = 1; j <= n; ++j)
        D[pos][j] = C[j];
}

int main() {
    ifstream fin("ubuntzei.in");
    ofstream fout("ubuntzei.out");
    int n, m, k;
    fin >> n >> m >> k;
    for (int i = 1; i <= k; ++i) {
        fin >> O[i];
    }
    O[0] = 1;
    for (int i = 1; i <= m; ++i) {
        int a, b, c;
        fin >> a >> b >> c;
        L[a].push_back(make_pair(b, c));
        L[b].push_back(make_pair(a, c));
    }

    for (int i = 0; i <= k; ++i)
        dijkstra(i, n);

    int kmax = 1 << k;

    for (int i = 1; i < kmax; ++i)
        for (int j = 1; j <= k; ++j)
            R[i][j] = INF;
    for (int set = 1, i = 1; i <= k; set <<= 1, ++i)
        R[set][i] = D[0][O[i]];

    for (int set = 1; set < kmax; ++set)
        for (int step = 1, i = 1; step <= set; step <<= 1, ++i)
            if (set & step) {
                int oset = set ^ step;
                for (int step2 = 1, j = 1; step2 <= oset; step2 <<= 1, ++j) {
//                    if (oset & step2) {
//                        int nc = R[oset][j] + D[j][O[i]];
//                        if (nc < R[set][i])
//                            R[set][i] = nc;
                        R[set][i] = min(R[set][i], R[oset][j] + D[j][O[i]]);
 //                   }
                }
            }

    int minn = INF;
    for (int i = 1; i <= k; ++i) {
        int nc = R[kmax - 1][i] + D[i][n];
        if (nc < minn)
            minn = nc;
    }

    fout << (k == 0 ? D[0][n] : minn) << "\n";

    return 0;
}