Cod sursa(job #977795)

Utilizator CosminRusuCosmin Rusu CosminRusu Data 26 iulie 2013 16:50:47
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.19 kb
#include <fstream>
#include <vector>
#include <bitset>
#include <queue>
#include <algorithm>
#include <utility>
#include <string.h>

using namespace std;

ifstream cin("ubuntzei.in");
ofstream cout("ubuntzei.out");

const int MAXN = 2005;
const int MAXK = 17;
const int oo = (1<<30);

typedef vector< pair<int, int> > Graph[MAXN];
typedef vector< pair<int, int> > :: iterator It;

Graph G;
int N, M, K, U[MAXK], D[MAXK][MAXN], dp[1<<MAXK][MAXK];
vector<int>d(MAXN);
priority_queue <pair<int, int> , vector<pair<int, int> > , greater<pair<int, int> > > Q;
inline int bit_count(int x) {
    return !x ? 0 : 1 + bit_count(x & (x - 1));
}
const inline void Dijkstra(int Source){   // fucking economic
    int Node;
    for(Q.push(make_pair(0, Source)), d[Source] = 0, Node = Source ; !Q.empty() ; Q.pop() , Node = Q.top().second)
        for(It it = G[Node].begin(), fin = G[Node].end() ; it != fin ; ++ it)
            if(d[it->first] > d[Node] + it->second)
                d[it->first] = d[Node] + it->second, Q.push(make_pair(d[it->first], it->first));
}
int main(){
    cin >> N >> M >> K;
    for(int i = 1 ; i <= K ; ++ i)
        cin >> U[i];
    U[0] = 1 ; U[K+1] = N;
    for(int i = 1 ; i <= M ; ++ i){
        int X, Y, Cost;
        cin >> X >> Y >> Cost;
        G[X].push_back(make_pair(Y, Cost));
        G[Y].push_back(make_pair(X, Cost));
    }
    for(int i = 0 ; i <= K + 1 ; ++ i){
        fill(d.begin(), d.end(), oo);
        Dijkstra(U[i]);
        for(int j = 0 ; j <= K + 1 ; ++ j)
            D[i][j] = d[U[j]];
    }
    memset(dp, oo, sizeof(dp));
    for(int i = 1 ; i < (1 << K) ; ++ i)
        for(int j = 0 ; j < K ; ++ j){
            if (((i >> j) & 1) == 0) continue;

            if (bit_count(i) == 1) {
                dp[j][i] = D[0][j + 1];
                continue;
            }
            for (int k = 0; k < K; ++K)
                if ((i >> k) & 1)
                    dp[j][i] = min(dp[j][i], dp[k][i ^ (1 << j)] + D[k + 1][j + 1]);
        }
    int Ans = oo;
    for(int i = 0 ; i < K ; ++ i)
        Ans = min(Ans, dp[i][(1<<K)-1] + D[i+1][K+1]);
    cout << Ans << "\n";
    cin.close();
    cout.close();
    return 0;
}