Cod sursa(job #1052203)

Utilizator toranagahVlad Badelita toranagah Data 10 decembrie 2013 22:16:18
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.62 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

const int MAX_N = 2100;
const int MAX_M = 10100;
const int MAX_K = 18;
const int INF = 1 << 30;

int N, M, K;
vector<pair<int, int>> graph[MAX_N];
vector<int> incoming[MAX_K];
int cost[MAX_K][MAX_K];
int d[MAX_K][1 << MAX_K];
vector<int> ubuntzei;

void read_input();
void solve();
vector<int> dijkstra(int source);
int hamilton();

int main() {
    read_input();
    solve();
}

void read_input() {
    fin >> N >> M;

    fin >> K;
    K += 2;
    ubuntzei.resize(K);
    for (int i = 1; i < K - 1; ++i) {
        fin >> ubuntzei[i];
    }
    ubuntzei[0] = 1;
    ubuntzei[K - 1] = N;

    for (int i = 1, a, b, c; i <= M; ++i) {
        fin >> a >> b >> c;
        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
    }
}

void solve() {
    for (int i = 0; i < K; ++i) {
        vector<int> dist = dijkstra(ubuntzei[i]);

        for (int j = 0; j < K; ++j) {
            if (i == j) continue;
            if (dist[ubuntzei[j]] < INF) {
                incoming[j].push_back(i);
                cost[i][j] = dist[ubuntzei[j]];
            }
        }
    }

    fout << hamilton();
}


struct pq_cmp {
    bool operator()(const pair<int, int> &a, const pair<int, int> &b) const {
        return a.second > b.second;
    }
};

vector<int> dijkstra(int source) {
    vector<int> dist(N + 1, INF);
    vector<bool> visited(N + 1, 0);

    dist[source] = 0;
    priority_queue<pair<int, int>, vector<pair<int, int>>, pq_cmp> pq;
    pq.push(make_pair(source, 0));

    while (!pq.empty()) {
        pair<int, int> node = pq.top();
        pq.pop();

        if (visited[node.first]) continue;
        visited[node.first] = true;

        for (auto x: graph[node.first]) {
            if (node.second + x.second < dist[x.first]) {
                dist[x.first] = node.second + x.second;
                pq.push(make_pair(x.first, dist[x.first]));
            }
        }
    }
    return dist;
}

int hamilton() {
    for (int conf = 0; conf < (1 << K); ++conf) {
        for (int i = 0; i < K; ++i) {
            d[conf][i] = INF;
        }
    }

    d[1][0] = 0;
    for (int conf = 0; conf < (1 << K); ++conf) {
        for (int j = 0; j < K; ++j) {
            if ((1 << j) && conf) {
                for (int i: incoming[j]) {
                    if ((1 << i) & conf) {
                        d[conf][j] = min(d[conf][j], d[conf ^ (1 << j)][i] + cost[i][j]);
                    }
                }

            }
        }
    }

    return d[(1 << K) - 1][K - 1];
}