Cod sursa(job #791769)

Utilizator SchumiDumitru Andrei Georgian Schumi Data 25 septembrie 2012 12:21:33
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.57 kb
#include <cassert>
#include <cstdio>
#include <cstring>

#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

#define FORIT(it, v) for (typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)

const int INF = 0x3f3f3f3f;
const int K = 16;
const int N = 2005;

int n, m, k;
int orase[K];
int d[1 << K][K], dmin[N][N], dist[N];
vector <pair <int, int> > graf[N];

void read() {
    assert(freopen("ubuntzei.in", "r", stdin) != NULL);
    
    assert(scanf("%d %d %d", &n, &m, &k) == 3);
    for (int i = 1; i <= k; ++i)
        assert(scanf("%d", &orase[i]) == 1);
    orase[0] = 1;
    orase[k + 1] = n;

    for (int i = 1; i <= m; ++i) {
        int x, y, z;
        assert(scanf("%d %d %d", &x, &y, &z) == 3);
        graf[x].push_back(make_pair(y, z));
        graf[y].push_back(make_pair(x, z));
    }
}

void dijkstra(int source) {
    memset(dist, INF, sizeof(dist));

    priority_queue <pair <int, int>, vector <pair <int, int> >, greater <pair <int, int> > > heap;
    heap.push(make_pair(0, source));

    while (!heap.empty()) {
        pair <int, int> nodCurent = heap.top();
        heap.pop();
        
        if (dist[nodCurent.second] != INF)
            continue;
        dist[nodCurent.second] = nodCurent.first;

        FORIT(it, graf[nodCurent.second])
            if (dist[it->first] == INF)
                heap.push(make_pair(nodCurent.first + it->second, it->first));
    }
}

void minDist() {
    for (int i = 0; i <= k + 1; ++i) {
        dijkstra(orase[i]);
        for (int j = 0; j <= k + 1; ++j)
            dmin[i][j] = dist[orase[j]];
    }
}

int biti(int x) {
    return !x ? 0 : 1 + biti(x & (x - 1));
}

void dinamica() {
    memset(d, INF, sizeof(d));

    for (int conf = 1; conf < (1 << k); ++conf)
        for (int last = 0; last < k; ++last) {
            if (!(conf & (1 << last)))
                continue;

            if (biti(conf) == 1) {
                d[conf][last] = dmin[0][last + 1];
                continue;
            }

            for (int newLast = 0; newLast < k; ++newLast) {
                if (conf & (1 << newLast))
                    continue;

                d[conf | (1 << newLast)][newLast] = min(d[conf | (1 << newLast)][newLast], d[conf][last] + dmin[last + 1][newLast + 1]);
            }
        }
}

void print() {
    assert(freopen("ubuntzei.out", "w", stdout) != NULL);

    int sol = INF;
    for (int i = 0; i < k; ++i)
        sol = min(sol, d[(1 << k) - 1][i] + d[i + 1][k + 1]);
    if (k == 0)
        sol = d[0][1];

    printf("%d", sol);
}

int main() {
    read();
    minDist();
    dinamica();
    print();
}