Cod sursa(job #653420)

Utilizator skipyGiurgea Mihnea skipy Data 27 decembrie 2011 22:22:19
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.82 kb
#include <cstdio>
#include <cstring>
#include <cassert>

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

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

const int INF = 0x3f3f3f3f;
const int MAXN = 2013;
const int MAXM = 10013;
const int MAXK = 20;
const int MAXCONF = 32768;

vector< pair<int,int> > G[MAXN];
int N, M, K;
int D[MAXCONF][MAXK], dist[MAXK][MAXN], ubuntzei[MAXK];

void read() {
    assert(scanf("%d %d", &N, &M) == 2);
    assert(scanf("%d", &K) == 1);
    for (int i = 0; i < K; i++)
        scanf("%d", &ubuntzei[i]);
    int x, y, c;
    for (int i = 0; i < M; i++) {
        assert(scanf("%d %d %d", &x, &y, &c) == 3);
        G[x].push_back( make_pair(y, c) );
        G[y].push_back( make_pair(x, c) );        
    }
}

void dijkstra(int start, int D[]) {
    priority_queue< pair<int, int>, vector< pair<int, int> >, greater< pair<int, int> > > heap;
    pair<int, int> top;
    int k;
    
    for (int i = 1; i <= N; i++) D[i] = INF;
    
    D[start] = 0;
    heap.push( make_pair(0, start) );

    for (int i = 0; i < N - 1; i++) {
        do {
            top = heap.top();
            k = top.second;
            heap.pop();
        } while (D[k] == INF);

        FORIT(it, G[k])
            if (D[it->first] == INF) {
                D[it->first] = min(D[it->first], D[k] + it->second);
                heap.push( make_pair(D[it->first], it->first) );
            }
    }
}

int solve() {
    if (!K) {
        dijkstra(1, dist[0]);
        return dist[0][N];
    }
    
    // Compute shortest paths from source + all K ubuntzei.
    for (int i = 0; i < K; i++)
        dijkstra(ubuntzei[i], dist[i]);
        
    int c, best;
    
    // Compute D[conf, i].
    D[0][0] = 0;
    for (int conf = 1; conf < (1 << K); conf++) {
        
        for (int i = 0; i < K; i++)
            if (conf & (1 << i)) {
                // Compute D[conf][i] = min(...)
                c = conf ^ (1 << i);
                if (c) {
                    best = INF;
                    for (int j = 0; j < K; j++)
                        if (c & (1 << j)) 
                            best = min(best, D[c][j] + dist[i][ ubuntzei[j] ]);
                    D[conf][i] = best;
                } else {
                    D[conf][i] = dist[i][1];
                }
            }
        /*printf("D[%d]: ", conf);
        for (int i = 0; i < K; i++)
            printf("%d ", D[conf][i]);
        printf("\n");*/
    }

    best = INF;
    c = (1 << K) - 1;
    for (int i = 0; i < K; i++)
        if (c & (1 << i))
            best = min(best, D[c][i] + dist[i][N]);

    return best;
}

int main() {
    assert(freopen("ubuntzei.in", "r", stdin));
    // assert(freopen("ubuntzei.out", "w", stdout));
    
    read();
    printf("%d\n", solve());
    
    return 0;
}