Cod sursa(job #2048372)

Utilizator Alex18maiAlex Enache Alex18mai Data 25 octombrie 2017 23:00:49
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.99 kb
#include <fstream>
#include <vector>
#include <queue>
#include <map>

using namespace std;

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

class cmp{
public:
    bool operator() (pair<int , int> &a , pair<int , int> &b){
        return a.second > b.second;
    }
};

int n , m , k;
int K[20];
map <int , bool> is_k;
int dp[2005];
int dp_x[(1<<15) + 5][20];
vector < vector < pair<int , int> > > gr(2005);
int gr_k [2005][20];
priority_queue <pair<int , int> , vector<pair<int , int>> , cmp> Q;

const int inf = 2e9;

void put_inf(){
    for (int i=1; i<=n; i++){
        dp[i] = inf;
    }
}

void dijkstra(int root, bool zero){

    put_inf();

    if (zero){
        Q.push({1 , 0});
        dp[1] = 0;
    }
    Q.push({K[root] , 0});
    dp[K[root]] = 0;

    while (!Q.empty()){
        pair<int , int> now = Q.top();
        Q.pop();
        if (dp[now.first] != now.second){
            continue;
        }
        for (auto &x : gr[now.first]){
            if (dp[x.first] > now.second + x.second){
                dp[x.first] = now.second + x.second;
                Q.push({x.first , dp[x.first]});
            }
        }
    }

    if (zero){
        cout<<dp[n];
        return;
    }

    if (dp[1] != inf){
        gr_k[root][0] = dp[1];
    }

    if (dp[n] != inf){
        gr_k[root][k+1] = dp[n];
    }

    for (int i=1; i<=k; i++){
        if (dp[K[i]] != inf){
            gr_k[root][i] = dp[K[i]];
        }
    }
}

void make_dp_x(){

    for (int mask=0; mask < (1<<k); mask++){
        for (int last = 0; last < k; last++){
            dp_x[mask][last] = inf;
        }
    }

    dp_x[0][0] = 0;

    for (int mask=0; mask < (1<<k); mask++){
        for (int last = 0; last < k; last++){
            if (dp_x[mask][last] == inf){
                continue;
            }
            for (int bit=0; bit < k; bit++){
                if ((1 << bit) & mask){
                    continue;
                }
                if (mask == 0){
                    if (gr_k[bit+1][0] != 0){
                        dp_x[mask ^ (1<<bit)][bit] = min (dp_x[mask ^ (1<<bit)][bit] , gr_k[bit+1][0]);
                    }
                    continue;
                }
                if (gr_k[last+1][bit+1] != 0){
                    dp_x[mask ^ (1<<bit)][bit] = min (dp_x[mask ^ (1<<bit)][bit] , dp_x[mask][last] + gr_k[last+1][bit+1]);
                }
            }
        }
    }

    int MIN = inf;

    for (int i=0; i<k; i++){
        if (gr_k[i+1][k+1] != 0){
            MIN = min (MIN , dp_x[(1 << k) - 1][i] + gr_k[i+1][k+1]);
        }
    }

    cout<<MIN;
}

int main() {

    cin>>n>>m;

    cin>>k;
    for (int i=1; i<=k; i++){
        cin>>K[i];
        is_k[K[i]] = true;
    }

    for (int i=1; i<=m; i++){
        int a , b , dist;
        cin>>a>>b>>dist;
        gr[a].push_back({b , dist});
        gr[b].push_back({a , dist});
    }

    if (k == 0){
        dijkstra(1, true);
        return 0;
    }

    for (int i=1; i<=k; i++){
        dijkstra(i, false);
    }

    make_dp_x();

    return 0;
}