Cod sursa(job #1592462)

Utilizator lflorin29Florin Laiu lflorin29 Data 7 februarie 2016 17:24:42
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.13 kb
#include <bits/stdc++.h>

using namespace std;

static const int kInfinite = (1LL << 29) - 1;

void addmask(pair<int, int>&state, const vector<int>&how) {
    if(how[state.first] != -1)
        state.second |= 1 << how[state.first];
}

void computePath(int starting, vector<pair<int, int>>& Path, const vector<vector<pair<int, int>>>&edges, const vector<int>& how)
{
    Path[starting] = pair<int, int>(0, how[starting] != -1 ? 1 << how[starting] : 0);
    auto comparefoo = [&Path] (const pair<int, int>&lhs, const pair<int, int>&rhs)
    {
        return Path[lhs.first] > Path[rhs.first];
    };

    vector<bool>visited(edges.size());
    priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(comparefoo)> atTop(comparefoo);
    atTop.push(make_pair(starting, how[starting] != -1 ? 1 << how[starting] : 0));

    while(!atTop.empty()) {
         auto the_vertex = atTop.top();
         atTop.pop();
         visited[the_vertex.first] = 0;

         for(auto itr : edges[the_vertex.first]) {
             if(Path[the_vertex.first].first + itr.second < Path[itr.first].first) {
                pair<int, int>newState(itr.first, the_vertex.second);
                addmask(newState, how);
                Path[itr.first] = make_pair(Path[the_vertex.first].first + itr.second, newState.second);

                 if(visited[itr.first] == false) {
                     visited[itr.first] = true;
                     atTop.push(newState);
                 }
             }
         }
    }
}

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

    int M, K, N;
    cin >> N >> M >> K;

    vector<int>Town(K), how(N, -1);
    int MAsk = 0;
    for(int i = 0; i < K; ++i) {
        cin >> Town[i];
        Town[i]--; how[Town[i]] = i;
        MAsk |= 1 << i;
    }

    vector<vector<pair<int, int>>> Lis(N);
    for(int i = 0; i < M; ++i) {
        int Src, Dest, whtcost;
        cin >> Src >> Dest >> whtcost;
        Src--; Dest--;
        Lis[Src].emplace_back(Dest, whtcost); Lis[Dest].emplace_back(Src, whtcost);
    }

    vector<vector<pair<int, int>>>minimumPath(K + 1, vector<pair<int, int>>(N, pair<int, int>(kInfinite, 0)));
    for(int i = 0; i < K; ++i)
        computePath(Town[i], minimumPath[i], Lis, how);

    computePath(0, minimumPath[K], Lis, how);
    const auto&drum_din_0 = minimumPath[K];
    vector<vector<int>>DP(K, vector<int>(MAsk + 1, kInfinite));
    for(int i = 0; i < K; ++i)
        DP[i][drum_din_0[Town[i]].second] = drum_din_0[Town[i]].first;

      for(int Last = 0; Last < K; ++Last)
    for(int conf = 0; conf <= MAsk; ++conf)
         for(int Next = 0; Next < K; ++Next) {
            if(Next == Last) continue;

            pair<int, int>Dist_N_Mask = minimumPath[Last][Town[Next]];

            int newConf = (conf | Dist_N_Mask.second);
            int &dpaux = DP[Next][newConf];
            dpaux = min(dpaux, DP[Last][conf] + Dist_N_Mask.first);
         }

    int Result = kInfinite;
    for(int i = 0; i < K; ++i)
        Result = min(Result, DP[i][MAsk] + minimumPath[i][N - 1].first);
    cout << Result;
    return 0;
}