Cod sursa(job #594877)

Utilizator nandoLicker Nandor nando Data 10 iunie 2011 11:25:02
Problema Ubuntzei Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <bitset>
#include <queue>
using namespace std;

#define min(a, b) (((a) < (b)) ? (a) : (b))

#define MAXN 2010
#define MAXK 18
#define INF 0x3f3f3f3f

#define node first
#define dist second

int n, m, k;
int src[MAXK];
int d[MAXK][MAXN];
int dist[MAXK][MAXK], cost[1 << MAXK][MAXK];

vector <pair <int, int> > g[MAXN];
typedef vector <pair <int, int> >::iterator iter;

void dijkstra (int s)
{
    for (int i = 1; i <= n; ++i) {
        d[s][i] = INF;
    }

    d[s][src[s]] = 0;

    bitset <MAXN> viz;
    priority_queue <pair <int, int> > q;
    q.push (make_pair (0, src[s]));

    while (!q.empty ()) {
        int nd = q.top ().second;
        viz[nd] = true;
        q.pop ();

        for (iter it = g[nd].begin (); it != g[nd].end (); ++it) {
            if (!viz[it->node] && d[s][nd] + it->dist < d[s][it->node]) {
                d[s][it->node] = d[s][nd] + it->dist;
                q.push (make_pair (-d[s][it->node], it->node));
            }
        }
    }
}

void computeDist ()
{
    for (int i = 0; i < k; ++i) {
        for (int j = 0; j < k; ++j) {
            dist[i][j] = d[i][src[j]];
        }
    }
}

int hamilton ()
{
    for (int i = 1; i < (1 << k); ++i) {
        for (int j = 0; j < k; ++j) {
            cost[i][j] = INF;
        }
    }
    cost[1][0] = 0;

    for (int i = 1; i < (1 << k); ++i) {
        for (int j = 0; j < k; ++j) {
            if (i & (1 << j)) {
                for (int l = 0; l < k; ++l) {
                    if (i & (1 << l)) {
                        cost[i][j] = min(cost[i][j], cost[i ^ (1 << j)][l] + dist[l][j]);
                    }
                }
            }
        }
    }

    return cost[(1 << k) - 1][k - 1];
}

int main ()
{
    FILE* fin = fopen ("ubuntzei.in", "r");
    FILE* fout = fopen ("ubuntzei.out", "w");

    fscanf (fin, "%d %d\n%d", &n, &m, &k);

    src[0] = 1;
    for (int i = 1; i <= k; ++i) {
        fscanf (fin, "%d", &src[i]);
    }
    src[++k] = n, ++k;

    for (int i = 1; i <= m; ++i) {
        int x, y, z;
        fscanf (fin, "%d %d %d\n", &x, &y, &z);

        g[x].push_back (make_pair (y, z));
        g[y].push_back (make_pair (x, z));
    }

    for (int i = 0; i < k; ++i) {
        dijkstra (i);
    }

    computeDist ();

    fprintf (fout, "%d\n", hamilton ());

    fclose (fin);
    fclose (fout);
    return 0;
}