Cod sursa(job #923356)

Utilizator sebii_cSebastian Claici sebii_c Data 23 martie 2013 13:43:56
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.12 kb
#include <cstdio>
#include <cstring>

#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <vector>

using namespace std;

priority_queue<pair<int, int>, vector<pair<int, int> >, 
    greater<pair<int, int> > > pq;

const int INF = 0x3f3f3f3f;
const int MAXN = 2001;
const int MAXK = 16;

bool vis[MAXN];
map<int, vector<int> > dist;

int N, C;
vector<int> G[MAXN];
vector<int> Cst[MAXN];
vector<int> ubun;

int dp[1 << MAXK];

void dijkstra(int s)
{
    memset(vis, false, sizeof(vis));

    for (int i = 1; i <= N; ++i)
        dist[s][i] = INF;

    pq.push(make_pair(0, s));
    dist[s][s] = 0;
    while (!pq.empty()) {
        int node = pq.top().second;
        int cost = pq.top().first;
        pq.pop();
        
        if (vis[node])
            continue;
        vis[node] = true;

        for (int i = 0; i < G[node].size(); ++i) {
            int next = G[node][i];
            if (cost + Cst[node][i] < dist[s][next]) {
                dist[s][next] = cost + Cst[node][i];
                pq.push(make_pair(dist[s][next], next));
            }
        }
    }
}

int get_cost()
{
    int cost = 0;
    int st = 1;
    for (int i = 0; i < C; ++i) {
        cost += dist[st][ubun[i]];
        st = ubun[i];
    }

    return cost;
}

int get_best(int node, int config)
{
    set<int> rest;
    for (int j = 0; j < C; ++j)
        if (((1 << j) & config) != 0)
            rest.insert(j);

    if (rest.size() == 0)
        return 0;

    int best = (int)(1e9);
    set<int>::iterator it;
    for (it = rest.begin(); it != rest.end(); ++it) 
        best = min(best, dist[ubun[*it]][node]);

    return best;
}

int cost_last()
{
    return get_best(N, (1 << C) - 1);
}

int doit(int config)
{
    if (config == 0)
        return 0;
    if (dp[config] != -1)
        return dp[config];

    set<int> rest;
    for (int j = 0; j < C; ++j)
        if ((config & (1 << j)) != 0)
            rest.insert(j);

    if (rest.size() == 1) {
        dp[config] = dist[1][ubun[*rest.begin()]];
        return dp[config];
    }

    int best_cost = (int)(1e9);
    int conf = config;
    set<int>::iterator it;
    for (it = rest.begin(); it != rest.end(); ++it) {
        conf ^= (1 << (*it));
        int cost = get_best(ubun[*it], conf);
        best_cost = min(best_cost, doit(config ^ (1 << (*it))) + cost);
        conf ^= (1 << (*it));
    }

    dp[config] = best_cost;
    return best_cost;
}

int main()
{
    freopen("ubuntzei.in", "r", stdin);
    freopen("ubuntzei.out", "w", stdout);

    int M;
    scanf("%d %d", &N, &M);

    scanf("%d", &C);
    for (int i = 0; i < C; ++i) {
        int x;
        scanf("%d", &x);
        ubun.push_back(x);
        dist[x] = vector<int>(N + 1);
    }
    dist[1] = vector<int>(N + 1);
    dist[N] = vector<int>(N + 1);

    for (int i = 0; i < M; ++i) {
        int x, y, c;
        scanf("%d %d %d", &x, &y, &c);
        G[x].push_back(y);
        Cst[x].push_back(c);
        G[y].push_back(x);
        Cst[y].push_back(c);
    }

    dijkstra(1);
    for (int i = 0; i < C; ++i)
        dijkstra(ubun[i]);

    memset(dp, -1, sizeof(dp));

    printf("%d\n", doit((1 << C) - 1) + cost_last());

    return 0;
}