Cod sursa(job #1540662)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 2 decembrie 2015 23:59:50
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.85 kb
#include <cstdio>
#include <queue>
#include <bitset>
#include <algorithm>

#define value first
#define cost second
using namespace std;

const int INF  = 1073741824;
const int DIM1 = 2048;
const int DIM2 = 18;

int nrNodes, nrEdges, nrCities, Hamilton[(1<<DIM2)][DIM2], Distance[DIM2][DIM2], D[DIM1], Cities[DIM1];
vector <pair <int, int> > Edges[DIM1]; bitset <DIM1> Marked; queue <int> Queue; int node1, node2, dist;

inline void resetValues (int startNode) {

    for (int i = 0; i < nrNodes; i ++)
        D[i] = INF;

    while (!Queue.empty())
        Queue.pop();

    Marked.reset();

    Queue.push(startNode);
    Marked[startNode] = 1;
    D[startNode] = 0;

    return;
}

inline int getDistance (int startNode, int finishNode) {
    resetValues (startNode);

    while (!Queue.empty()) {
        int node = Queue.front();

        vector <pair <int, int> > :: iterator it;
        for (it = Edges[node].begin(); it != Edges[node].end(); it ++) {
            pair <int, int> nextNode = *it;

            if (D[nextNode.value] > D[node] + nextNode.cost) {
                D[nextNode.value] = D[node] + nextNode.cost;

                if (!Marked[nextNode.value]) {
                    Marked[nextNode.value] = 1;
                    Queue.push(nextNode.value);
                }
            }
        }
        Marked[node] = 0;
        Queue.pop();
    }

    return D[finishNode];
}

int main () {

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

    scanf ("%d", &nrNodes );
    scanf ("%d", &nrEdges );
    scanf ("%d", &nrCities);

    Cities[0] = 0;
    for (int i = 1; i <= nrCities; i ++) {
        scanf ("%d", &Cities[i]);
        Cities[i] --;
    }
    Cities[++nrCities] = nrNodes - 1;
    nrCities ++;

    for (int i = 1; i <= nrEdges; i ++) {
        scanf ("%d %d %d", &node1, &node2, &dist);
        node1 --; node2 --;

        Edges[node1].push_back(make_pair(node2, dist));
        Edges[node2].push_back(make_pair(node1, dist));
    }

    for (int i =   0  ; i < nrCities; i ++)
    for (int j = i + 1; j < nrCities; j ++)
        Distance[i][j] = Distance[j][i] = getDistance (Cities[i], Cities[j]);

    for (int i = 0; i < (1<<nrCities); i ++)
        for (int j = 0; j < nrCities; j ++)
            Hamilton[i][j] = INF;

    Hamilton[1][0] = 0;
    for (int i = 1; i < (1<<nrCities); i ++) {
    for (int j = 0; j < nrCities; j ++) {

        if (!(i&(1<<j)))
            continue;

        for (int k = 0; k < nrCities; k ++) {

            if (i&(1<<k))
                continue;

            if (Hamilton[i+(1<<k)][k] > Hamilton[i][j] + Distance[j][k])
                Hamilton[i+(1<<k)][k] = Hamilton[i][j] + Distance[j][k];
        }

    }}

    printf ("%d\n", Hamilton[(1<<nrCities)-1][nrCities-1]);

    return 0;
}