Cod sursa(job #2025985)

Utilizator antanaAntonia Boca antana Data 23 septembrie 2017 15:33:56
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.6 kb
#include <bits/stdc++.h>

using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 2e3 + 5;
const int MAXM = 1e4 + 5;
const int MAXK = 17;

FILE *fin, *fout;

int d[MAXN];

class compare {
public:
    bool operator() (int &x, int &y) {
        return d[ x ] > d[ y ];
    }
};

vector < pair <int, int > > G[MAXN];
priority_queue < int, vector <int>, compare > heap;

int n, m, k, nodes[MAXK], start[MAXN], dist[MAXK][MAXK], best[(1<<(MAXK-1))][MAXK];

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

    while(!heap.empty())
        heap.pop();

    heap.push( node );
    while (!heap.empty()) {
        node = heap.top();
        heap.pop();

        for (pair <int, int> edge: G[ node ])
            if (d[ edge.first ] > d[ node ] + edge.second) {
                d[ edge.first ] = d[ node ] + edge.second;
                heap.push( edge.first );
            }
    }
}

int main()
{
    fin = fopen( "ubuntzei.in", "r" );
    fout= fopen( "ubuntzei.out","w" );

    int x, y, z;

    fscanf( fin, "%d%d%d", &n, &m, &k );

    for (int i = 0; i < k; i++)
        fscanf( fin, "%d", &nodes[ i ] );

    for (int i = 1; i <= m; i++) {
        fscanf( fin, "%d%d%d", &x, &y, &z );
        G[ x ].push_back( {y, z} );
        G[ y ].push_back( {x, z} );
    }

    dijkstra( 1 );
    for (int i = 1; i <= n; i++)
        start[ i ] = d[ i ];

    if (k == 0) {
        fprintf( fout, "%d", start[ n ] );
        return 0;
    }

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

    for (int i = 0; i < k; i++) {
        dijkstra( nodes[ i ] );
        for (int j = 0; j < k; j++)
            if (i != j)
                dist[ i ][ j ] = d[ nodes[ j ] ];
            else
                dist[ i ][ j ] = 0;
        dist[ i ][ k ] = d[ n ];
    }

    memset( best, 0x3f, sizeof best );

    for (int i = 0; i < k; i++)
        best[ (1<<i) ][ i ] = start[ nodes[ i ] ];

    for (int i = 1; i < (1<<k); i++)
        for (int j = 0; j < k; j++)
            if (((1<<j) & i) && best[ i ][ j ] == INF)
                for (int t = 0; t < k; t++)
                    if (t != j && ((1<<t) & i))
                        best[ i ][ j ] = min( best[ i ][ j ], best[ i-(1<<j) ][ t ] + dist[ t ][ j ] );

    int answer = INF;

    for (int j = 0; j < k; j++)
        answer = min( answer, best[ (1<<k)-1 ][ j ] + dist[ j ][ k ] );

    fprintf( fout, "%d", answer );

    fclose( fin );
    fclose( fout );

    return 0;
}