Cod sursa(job #1121453)

Utilizator valiro21Valentin Rosca valiro21 Data 25 februarie 2014 12:52:47
Problema Ubuntzei Scor 55
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.77 kb
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <algorithm>

#define NMax 2001
#define Inf 1<<30

using namespace std;

long n, m, k, x, y, z, now, nr, minNr;
long a[21], b[21], cost[21][NMax], v[21][21];
vector<pair<long, long> > edge[NMax];
bool viz[21];
map<set<long>, long> mp[21][21];
set<long> st, all, notSt;

void computeMinimalRoadFrom ( long ind, long now ) {
    set<pair<long, long> > q;

    for ( long i = 1; i <= n; i++ )
        cost[ind][i] = Inf;

    q.insert ( make_pair ( 0, now ) );
    cost[ind][now] = 0;
    while ( !q.empty ( ) ) {
        now = q.begin ( )->second;
        q.erase ( q.begin ( ) );

        for ( long i = 0; i < edge[now].size ( ); i++ )
            if ( cost[ind][now] + edge[now][i].second < cost[ind][edge[now][i].first] )
                cost[ind][edge[now][i].first] = cost[ind][now] + edge[now][i].second,
                q.insert ( make_pair ( cost[ind][edge[now][i].first], edge[now][i].first ) );
    }
}

void bkt ( );

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

    scanf ( "%ld %ld %ld", &n, &m, &k );
    for ( long i = 1; i <= k; i++ )
        scanf ( "%ld", &a[i] );

    for ( long i = 1; i <= m; i++ )
        scanf ( "%ld %ld %ld", &x, &y, &z ),
        edge[x].push_back ( make_pair ( y, z ) ),
        edge[y].push_back ( make_pair ( x, z ) );


    a[0] = 1;
    a[k + 1] = n;
    for ( long i = 0; i <= k + 1; i++ )
        computeMinimalRoadFrom ( i, a[i] );

    if ( k == 0 )
        minNr = cost[0][n];
    else
        bkt ( );

    printf ( "%ld\n", minNr );

    return 0;
}


void bkt ( ) {
    all.insert ( 0 );
    for ( long j = 1; j <= k; j++ ) {
        all.insert ( j );
        st.clear ( ); st.insert ( 0 ); st.insert ( j );
        mp[1][j][st] = cost[0][a[j]];
    }

    for ( long l = 1; l < k; l++ )
        for ( long j = 1; j <= k; mp[l][j].clear (), j++ )
            for ( map<set<long>, long>::iterator it = mp[l][j].begin ( ); it != mp[l][j].end ( ); it++ ) {
                notSt.clear ( );
                set_difference ( all.begin ( ), all.end ( ), it->first.begin ( ), it->first.end ( ), inserter ( notSt, notSt.end ( ) ) );
                for ( set<long>::iterator i = notSt.begin ( ); i != notSt.end ( ); i++ ) {
                    st = it->first; st.insert ( *i );
                    nr = it->second + cost[j][a[*i]];
                    if ( nr < mp[l + 1][*i][st] || mp[l + 1][*i][st] == 0 )
                        mp[l + 1][*i][st] = nr;
                }
            }

    minNr = Inf;
    for ( long j = 1; j <= k; j++ )
        for ( map<set<long>, long>::iterator it = mp[k][j].begin ( ); it != mp[k][j].end ( ); it++ ) {
            nr = it->second + cost[j][a[k+1]];
            if ( nr < minNr )
                minNr = nr;
        }
}