Cod sursa(job #2356084)

Utilizator Andrei-27Arhire Andrei Andrei-27 Data 26 februarie 2019 14:49:33
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.84 kb
#import<bits/stdc++.h>
#define pb push_back
#define mp make_pair
using namespace std;
ifstream in("ubuntzei.in");
ofstream out("ubuntzei.out");
const int oo = ( 1 << 30 ) ;
bool inq [ 2005 ] ;
vector < pair < int , int > > v [ 2005 ] ;
vector < int > d ( 2005 , oo ) ;
int n , m , k , st [ 2005 ] ;
int dist [ 18 ][ 18 ] ;
int dp [ 18 ][ ( 1 << 17 ) + 1 ] ;
struct cmp
{
    bool operator ()( int i , int j )
    {
        return d [ i ] > d [ j ] ;
    }
};
priority_queue < int , vector < int > , cmp > q;
void input()
{
    int x , y , z , i ;
    in >> n >> m ;
    in >> k ;
    st [ 0 ] = 1 ;
    for ( i = 1 ; i <= k ; ++ i ) in >> st [ i ] ;
    st [ ++ k ] = n ;
    while ( m -- )
    {
        in >> x >> y >> z ;
        v [ x ].pb( mp ( y , z ) ) ;
        v [ y ].pb( mp ( x , z ) ) ;
    }
}

void dijkstra ( int start )
{
    int nod , cost , vecin , i ;
    for ( i = 1 ; i <= n ; ++ i )   d [ i ] = oo ;
    q.push( st [ start ] ) ;
    d [ st [ start ] ] = 0 ;

    while ( !q.empty() )
    {
        nod = q.top() ;
        q.pop() ;

        inq [ nod ] = 0 ;
        for ( size_t i = 0 ; i < v [ nod ].size() ; ++ i )
        {
            vecin = v [ nod ][ i ].first ;
            cost = v [ nod ][ i ].second ;
            if ( cost + d[ nod ] < d [ vecin ] )
            {
                d [ vecin ] = cost + d [ nod ] ;
                if ( !inq [ vecin ] )   q.push( vecin ) ;
                inq [ vecin ] = 1 ;
            }
        }
    }
    for ( i = 0 ; i <= k ; ++ i )
        dist [ start ][ i ] = d [ st [ i ] ] ;
}

void build()
{
    // de aici ne intereaza doar cele k noduri
    // dist [ i ][ j ] - distanta de la i la j
    // dp [ i ][ S ] -  distanta minima parcursa vizitand nodurile din submultimea S
    //                  astfel incat la final sa te afli in nodul i
    int i , j ;
    for ( i = 0 ; i <= k ; ++ i )
        dijkstra( i ) ;
    for ( i = 0 ; i <= k ; ++ i )
    for ( j = 0 ; j <= ( 1 << k ) ; ++ j )
        dp [ i ][ j ] = oo ;

}

void aply_dp ()
{
     int i , j , p , l , sol ;
    dp [ 0 ][ 1 ] = 0 ;
    l = ( 1 << k ) ;
    for ( i = 1 ; i < l; i ++ )     // luam fiecare submultime decodificata din binar in baza 10 in i
    for ( j = 0 ; j <= k ; j ++)    // fiecare bit j de 1 al submultimii tine pozitia unui nod
    if ( ( i & ( 1 << j ) ) != 0 )  // pentru fiecare astfel de bit j

        for ( p = 0 ; p <= k ; ++ p )   //
        if ( ( i & ( 1 << p ) ) == 0 )  // luam fiecare bit de 0 si formam dinamica
            dp [ p ][ i | ( 1 << p ) ] = min ( dist [ j ][ p ] + dp [ j ][ i ] , dp [ p ][ i | ( 1 << p ) ] ) ;

    sol = oo ;
    for ( i = 0 ; i <= k ; ++ i )
        sol = min ( sol , dp [ i ][ l - 1 ] + dist [ i ][ k ]  ) ;
    out << sol ;
}
int main ()
{
    input() ;
    build() ;
    aply_dp() ;
}