Cod sursa(job #1251747)

Utilizator catalincraciunCraciun Catalin catalincraciun Data 29 octombrie 2014 21:05:03
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.71 kb
/// Craciun Catalin
///  Ubuntzei
///   OJI 2011
#include <iostream>
#include <fstream>
#include <vector>
#include <set>

#define mp make_pair
const int inf = 1<<30;
const int NMax = 2005;
const int KMax = 18;

using namespace std;

ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");

int n, m, k;
int toVisit[KMax]; /// Nodurile ce trebuie vizitate
int dmin[KMax];
int d[KMax][KMax]; /// d[i][j] = distanta minima de la d[toVisit[i]] la d[toVisit[j]]
int S[1<<KMax][KMax];

vector<int> V[NMax]; /// V[i] = lista cu vecinii lui i
vector<int> C[NMax]; /// C[i] = costul pentru a vizita vecinul i

set< pair<int, int> > q;

inline int minim(int a, int b) { if (a<b) return a; return b; };
inline void addNeighboorToNodeWithCost(int first, int second, int cost) {
    V[first].push_back(second); C[first].push_back(cost);
    V[second].push_back(first); C[second].push_back(cost);
}

void read() {

    f>>n>>m;
    f>>k;
    for (int i=1;i<=k;i++)
        f>>toVisit[i];
    for (int i=1;i<=m;i++) {
        int x,y,cost; f>>x>>y>>cost;
        addNeighboorToNodeWithCost(x,y,cost);
    }

    f.close();
}

void dijkstra(int source) {

    for (int i=1;i<=n;i++) {
        dmin[i] = inf;
    }
    dmin[source] = 0;

    q.insert(mp(0,source));
    while (!q.empty()) {
        int val = (*q.begin()).first; int key = (*q.begin()).second;
        q.erase(q.begin());
        int neigh = V[key].size();
        for (int i=0;i<neigh;i++) {
            if (dmin[V[key][i]] > val + C[key][i]) {
                dmin[V[key][i]] = val + C[key][i];
                q.insert(mp(dmin[V[key][i]], V[key][i]));
            }
        }
    }
}

int main() {

    read();
    if (!k) {
        /// Computing the road from 1 to n, that simple
        dijkstra(1);
        g<<d[n];
    } else {/*
        int lim = 1<<k;

        toVisit[0] = 1;
        for (int i=0;i<=k;i++) {
            dijkstra(toVisit[i]);
            for (int j=0;j<=k;j++) {
                d[i][j] = dmin[ toVisit[ j ] ];
            }
            d[i][k+1] = dmin[n];
        }

        for (int i=0;i<=lim;i++) {
            for (int j=0;j<=k;j++) {
                S[i][j] = inf;
            }
        }

        S[0][0] = 0;

        for (int mask=1;mask<lim;mask++) {
            for (int i=0;i<k;i++) {
                if (mask & (1<<i)) {
                    int mask2 = mask - (1<<i);
                    for (int j=0;j<=k;j++) {
                        S[mask][i+1] = minim(S[mask][i+1], S[mask2][j] + d[j][i+1]);
                    }
                }
            }
        }

        int sol = inf;
        for (int i=1;i<=k;i++) {
            sol = minim(sol, S[lim-1][i] + d[i][k+1]);
        }

        g<<sol<<'\n';*/

        toVisit[ 0 ] = 1;
        for(int i = 0; i <= k; ++i) {
            dijkstra( toVisit[i] );
            for(int j = 0; j <= k; ++j)
                d[i][j] = dmin[ toVisit[j] ];
            d[i][k + 1] = dmin[ n ];
        }

        int lim = ( 1 << k );
        for(int mask = 0; mask < lim; ++mask)
            for(int i = 0; i <= k; ++i)
                S[ mask ][ i ] = inf;

        S[ 0 ][ 0 ] = 0;

        for(int mask = 1; mask < lim; ++mask)
            for(int i = 0; i < k; ++i)
                if( mask & ( 1 << i  )) {
                    int mask2 = mask - (1 << i);
                    for(int j = 0; j <= k; ++j)
                        S[ mask ][ i + 1 ] = minim( S[mask][ i + 1 ], S[ mask2 ][ j ] + d[ j ][ i + 1 ]);
                }
        int sol = inf;

        for(int i = 1; i <= k; ++i)
            sol = min( sol, S[ lim - 1 ][ i ] + d[ i ][ k + 1 ]);

        g<<sol<<'\n';
    }

    g.close();

    return 0;
}