Cod sursa(job #1477919)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 27 august 2015 13:23:30
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.73 kb
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>

const int MAX_K = 15;
const int MAX_N = 2000;
const int BUFFSIZE = 4096;
const int INF = 2000000000;
const char IN [ ] = "ubuntzei.in" ;
const char OUT[ ] = "ubuntzei.out";

using namespace std;

#define pb emplace_back
#define mp make_pair

typedef pair < int, int > PII ;

ofstream cout( OUT );

//pentru parsare
char buffer [ BUFFSIZE ];
int pos = BUFFSIZE;

// date citite
int n;
int node [ MAX_K + 2 ];
vector < PII > adj [ MAX_N ];

// pentru dinamica
int dist [ MAX_K + 2 ][ MAX_K + 2 ];
int din  [ ( 1 << ( MAX_K + 2 ) ) ][ MAX_K + 2 ];

// pentru dijkstra
int d [ MAX_N ];
struct cmp
{
    bool operator () ( const int &a, const int &b )
    {
        if ( d [ a ] == d [ b ] )
            return a > b;
        return d [ a ] > d [ b ];
    }
};
priority_queue < int, vector < int > , cmp > heap;
bitset < MAX_N > seen ;

void dijkstra ( int nod )
{
    for ( int i = 0; i < n; i ++ )
        d [ i ] = INF;

    seen.reset ( );

    heap.push ( nod );
    d [ nod ] = 0;
    while ( !heap.empty ( ) )
    {
        nod = heap.top ( );
        heap.pop ( );

        if ( seen [ nod ] ) continue ;

        seen [ nod ] = 1;

        for ( auto u : adj [ nod ] )
        {
            int son = u.first;
            int newCost = d [ nod ] + u.second;

            if ( d [ son ] > newCost )
            {
                d [ son ] = newCost;
                heap.push ( son );
            }
        }
    }
}

inline char getChr ( )
{
    if ( pos == BUFFSIZE )
    {
        fread ( buffer, 1, BUFFSIZE, stdin );
        pos = 0;
    }
    return buffer [ pos ++ ];
}

inline int readInt ( )
{
    int q = 0;
    char c;

    do
    {
        c = getChr ( );
    } while ( !isdigit ( c ) );

    do
    {
        q = ( q << 1 ) + ( q << 3 ) + ( c - '0' );
        c = getChr ( );
    } while ( isdigit ( c ) );
    return q;
}

int main ( void )
{
    freopen ( IN, "r", stdin );
    int m, k;
    int u, v, c;

    n = readInt ( );
    m = readInt ( );
    k = readInt ( );

    node [ 0 ] = 0;
    for ( int i = 1; i <= k; i ++ )
        node [ i ] = readInt ( ) - 1;
    node [ k + 1 ] = n - 1;

    for ( int i = 0; i < m; i ++ )
    {
        u = readInt ( ) - 1;
        v = readInt ( ) - 1;
        c = readInt ( );
        adj [ u ].pb ( mp ( v, c ) );
        adj [ v ].pb ( mp ( u, c ) );
    }
    fclose ( stdin );

    for ( int i = 0; i <= k; i ++ )
    {
        dijkstra ( node [ i ] );
        for ( int j = 0; j <= k + 1; j ++ )
        {
            dist [ i ][ j ] = d [ node [ j ] ];
        }
    }

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

    for ( int i = 1; i < ( 1 << k ); i ++ )
    {
        for ( int j = 0; j < k; j ++ )
        {
            if ( ( i >> j ) & 1 )
            {
                if ( !( i & ( i - 1 ) ) )
                {
                    din [ i ][ j ] = dist [ 0 ][ j + 1 ];
                }
                else
                {
                    for ( int p = 0; p < k; p ++ )
                    {
                        if ( ( i >> p ) & 1 )
                            din [ i ][ j ] = min ( din [ i ][ j ], din [ i & ~( 1 << j ) ][ p ] + dist [ p + 1 ][ j + 1 ] );
                    }
                }
            }
        }
    }

    if ( !k )
        u = dist [ 0 ][ 1 ];
    else
    {
        u = INF;
        for ( int i = 1; i <= k; i ++ )
            u = min ( u, din [ ( 1 << k ) - 1 ][ i - 1 ] + dist [ i ][ k + 1 ] );
    }
    cout << u << '\n';
    cout.close ( );
    return 0;
}