Cod sursa(job #633693)

Utilizator Teodor94Teodor Plop Teodor94 Data 14 noiembrie 2011 16:10:16
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.48 kb
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>

using namespace std;

#define FORIT(it, v) for (typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)

const int INF = 0x3f3f3f3f;
const int N = 2005;
const int K = 16;

vector<pair<int, int> > v[N];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater< pair<int, int> > > heap;
int n, m, k, c[N], dist[N], d[K + 2][K + 2];
int dp[1 << K][K];

// priority_queue<T, vector<T>, greater<T>()> heap;

void citire() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= k; ++i)
        scanf("%d", &c[i]);

    int x, y, cost;
    for (int i = 1; i <= m; ++i){
        scanf("%d%d%d", &x, &y, &cost);
        v[x].push_back(make_pair(cost, y));
        v[y].push_back(make_pair(cost, x));
    }
}

void dijkstra(int nods) {
    memset(dist, 0, sizeof(dist)); // vector, valoare, sizeof

    heap.push(make_pair(0, nods));

    while (!heap.empty()) {
        pair <int, int> nodc = heap.top();

        heap.pop();

        if (!dist[nodc.second]) {
            dist[nodc.second] = nodc.first;

            FORIT (it, v[nodc.second])
                if (!dist[it->second])
                    heap.push(make_pair(nodc.first + it->first, it->second));
        }
    }

    dist[nods] = 0;
}

void init() {
    // am nev de dist min de la 1,n;
    c[0] = 1;
    c[k+1] = n;
    for (int i = 0; i <= k+1; ++i) {
        dijkstra(c[i]);
        for (int j = 0; j <= k+1; ++j)
            d[i][j] = dist[c[j]];
    }
}

void dinamica() {
    memset(dp, INF, sizeof(dp));
    for (int i = 1; i < (1 << k); ++i)
        for (int j = 0; j < k; ++j) {
            if (i & (1 << j) == 0) continue;
            // urmeaza sa calculam dp[i][j]

            // caz particular -> i contine un singur bit de 1
            if (i & (i - 1) == 0) {
                dp[i][j] = d[0][j + 1];
                continue;
            }

            // ne variem penultimul nod vizitat
            for (int last = 0; last < k; ++last)
                if (i & (1 << last) == 1 && last != j)
                    dp[i][j] = min(dp[i][j], dp[i ^ (1 << j)][last] + d[last + 1][j + 1]);
        }
}

void afis() {
    int best = INF;
    if (k == 0) best = d[0][k + 1];
    for (int i = 0; i < k; ++i)
        best = min(best, dp[(1 << k) - 1][i] + d[i + 1][k + 1]);
    printf("%d\n", best);
}

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

    citire();

    init();

    dinamica();

    afis();

    return 0;
}