Cod sursa(job #1876322)

Utilizator RobybrasovRobert Hangu Robybrasov Data 12 februarie 2017 11:31:44
Problema Ubuntzei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <fstream>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <bitset>
#define N 2001
#define K 17
#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][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];
}

void calculate(int n, int k) {
    int min = INF;
    for (int i = 1; i <= k; ++i) {
        // Construct the set without i
        int set = 0;
        for (int j = 1; j <= k; ++j)
            if (j != i)
                set += 1 << (C[j] - 1);
        // Go through the possibilities of finishing on node O[C[j]]
        int nset = set + (1 << (C[i] - 1));
        for (int j = 1; j <= k; ++j)
            if (j != i) {
                int nc = R[set][C[j]] + D[C[j]][O[C[i]]];
                if (nc < R[nset][C[i]])
                    R[nset][C[i]] = nc;
        }
    }
}

void comb(int l, int n, int k) {
    if (l <= k)
        for (int i = C[l - 1] + 1; i <= n - k + l; ++i) {
            C[l] = i;
            if (l == k){
                calculate(n, k);
            } else
                comb(l + 1, n, k);
        }
}

int main() {
    ifstream fin("ubuntzei.in");
    ofstream fout("ubuntzei.out");
    int n, m, k;
    fin >> n >> m >> k;
    for (int i = 2; i <= k + 1; ++i) {
        fin >> O[i];
    }
    O[1] = 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 = 1; i <= k + 1; ++i)
        dijkstra(i, n);

    for (int i = 1; i < 1 << (k + 1); ++i)
        for (int j = 1; j <= k + 1; ++j)
            R[i][j] = INF;

    for (int step = 2, i = 2; i <= k + 1; step <<= 1, ++i)
        R[step][i] = D[1][O[i]];

    C[0] = 1;
    for (int i = 2; i <= k + 1; ++i) {
        comb(1, k + 1, i);
    }

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

    fout << minn << "\n";

    return 0;
}