Cod sursa(job #1107853)

Utilizator dariusdariusMarian Darius dariusdarius Data 14 februarie 2014 15:46:09
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.39 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int MAX_N = 2005;
const int MAX_K = 17;
int dist[MAX_K][MAX_N];
int n, c[MAX_K];
int dp[1 << MAX_K][MAX_K];
vector< pair<int, int> > graph[MAX_N];
struct Node {
    int cost, node;
    Node() {}
    Node(int ccost, int nnode) {
        cost = ccost;
        node = nnode;
    }
    inline bool operator<(const Node &other) const {
        return cost > other.cost;
    }
};
void get_dist(int start, int line) {
    for(int i = 1; i <= n; ++ i) {
        dist[line][i] = -1;
    }
    dist[line][start] = 0;
    priority_queue<Node> heap;
    heap.push(Node(0, start));
    while(!heap.empty()) {
        Node best = heap.top();
        heap.pop();
        int node = best.node;
        for(vector< pair<int, int> > :: iterator it = graph[node].begin(); it != graph[node].end(); ++ it) {
            if(dist[line][it->first] == -1 || dist[line][it->first] > dist[line][node] + it->second) {
                dist[line][it->first] = dist[line][node] + it->second;
                heap.push(Node(dist[line][it->first], it->first));
            }
        }
    }
}
int main() {
    ifstream fin("ubuntzei.in");
    ofstream fout("ubuntzei.out");
    int m, k;
    fin >> n >> m >> k;
    for(int i = 1; i <= k; ++ i) {
        fin >> c[i];
    }
    for(int i = 1; i <= m; ++ i) {
        int x, y, cost;
        fin >> x >> y >> cost;
        graph[x].push_back(make_pair(y, cost));
        graph[y].push_back(make_pair(x, cost));
    }
    get_dist(1, 0);
    get_dist(n, k + 1);
    for(int i = 1; i <= k; ++ i) {
        get_dist(c[i], i);
    }
    for(int i = 1; i <= k; ++ i) {
        dp[1 << (i - 1)][i] = dist[0][c[i]];
    }
    for(int i = 2; i < (1 << k); ++ i) {
        if(!(i & (i - 1))) {
            continue;
        }
        for(int j = 1; j <= k; ++ j) {
            if(!(i & (1 << (j - 1)))) {
                continue;
            }
            dp[i][j] = 1000000000;
            for(int last = 1; last <= k; ++ last) {
                if(last != j && ((i & (1 << (last - 1))) == 0)) {
                    dp[i][j] = min(dp[i][j], dp[i ^ (1 << (j - 1))][last] + dist[last][c[j]]);
                }
            }
        }
    }
    int answer = 1000000000;
    for(int i = 1; i <= k; ++ i) {
        answer = min(answer, dp[(1 << k) - 1][i] + dist[i][n]);
    }
    fout << answer << "\n";
    return 0;
}