Cod sursa(job #1080751)

Utilizator gbi250Gabriela Moldovan gbi250 Data 12 ianuarie 2014 20:59:08
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#define SIZE 2002
#define mkp make_pair
#define inf 0x3f3f3f3f
using namespace std;

int n, m, k, MIN, father[SIZE], dist_tmp[SIZE], c[SIZE], dist_min[ 16 ][ SIZE ], DP[ SIZE ][ 15 ];
vector < pair <int, int> > g[SIZE];
queue <int> q;

inline void read()
{
    freopen("ubuntzei.in", "r", stdin);
    scanf("%d %d %d", &n, &m, &k);

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

    while( m-- )
    {
        int x, y, cost;
        scanf("%d%d%d", &x, &y, &cost);
        g[x].push_back(mkp(y, cost));
        g[y].push_back(mkp(x, cost));
    }
}

inline void dijkstra(int source)
{
    q.push( source );

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

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

        for( vector <pair <int, int> > :: iterator it = g[node].begin(); it != g[node].end(); ++it)
            if( dist_tmp[(*it).first] > dist_tmp[node] + (*it).second)
            {
                dist_tmp[(*it).first] = dist_tmp[node] + (*it).second;

                q.push((*it).first);
            }
    }
}

inline void solve()
{
    freopen("ubunztei.out", "w", stdout);
    if( !k )
    {
        dijkstra( 1 );
        printf("%d\n", dist_tmp[n]);
    }
    else
    {
        c[ 0 ] = 1;
        for(int i = 0; i <= k; ++i)
        {
            dijkstra( c[i] );
            for(int j = 0; j <= k; ++j)
                dist_min[i][j] = dist_tmp[ c[j] ];
            dist_min[i][k + 1] = dist_tmp[ n ];
        }

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

        DP[ 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)
                        DP[ mask ][ i + 1 ] = min( DP[mask][ i + 1 ], DP[ mask2 ][ j ] + dist_min[ j ][ i + 1 ]);
                }
        int sol = inf;

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

        printf("%d\n", sol);
    }
}

int main()
{
    read();
    solve();
    return 0;
}