Cod sursa(job #1580822)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 26 ianuarie 2016 10:18:41
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.11 kb
#include <cstdio>
#include <deque>
#include <vector>
#include <algorithm>
#include <bitset>

#define value first
#define cost second.first
#define maxim second.second

const int EXP = 1 << 4;
const int DIM = 1 << 10;
const long long INF = 1000000000000000LL;
using namespace std;

int V[EXP], K, N, M, X, Y, Z, T, NrBit[1 << EXP]; long long Dist[EXP + 1][EXP][EXP], D[1 << EXP][EXP], Distance[DIM];
vector <pair <int, pair <int, int> > > E[DIM]; bitset <DIM> Marked; deque <int> Queue; long long minim;

void bellman_ford( int start, int val_maxim ) {
    for( int i = 0; i < N; i ++ )
        Distance[i] = INF;
    Distance[start] = 0;

    Queue.clear(); Queue.push_back( start );
    Marked.reset(); Marked[start] = 1;

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

        vector <pair <int, pair <int, int> > > :: iterator it;
        for( it = E[node].begin(); it != E[node].end(); it ++ ) {
            pair <int, pair <int, int> > next_node = *it;

            if( next_node.maxim >= val_maxim ) {
                if( Distance[next_node.value] > Distance[node] + next_node.cost ) {
                    Distance[next_node.value] = Distance[node] + next_node.cost;

                    if( !Marked[next_node.value] ) {
                        Marked[next_node.value] = 1;
                        Queue.push_back( next_node.value );
                    }
                }
            }
        }

        Marked[node] = 0;
        Queue.pop_front();
    }

    return;
}

int main () {

    freopen( "gather.in" , "r", stdin  );
    freopen( "gather.out", "w", stdout );

    scanf( "%d %d %d", &K, &N, &M );
    for( int i = 1; i <= K; i ++ ) {
        scanf( "%d", &X );
        V[i] = X - 1;
    } K ++;

    for( int i = 1; i <= M; i ++ ) {
        scanf( "%d %d %d %d", &X, &Y, &Z, &T );
        E[X - 1].push_back( make_pair( Y - 1, make_pair( Z, T + 1 )));
        E[Y - 1].push_back( make_pair( X - 1, make_pair( Z, T + 1 )));
    }

    for( int k = 1; k <= 16; k ++ ) {
        for( int i = 0; i < K; i ++ ) {
            bellman_ford( V[i], k );

            for( int j = 0; j < K; j ++ )
                Dist[k][i][j] = Distance[V[j]] * 1LL * k;
        }
    }

    for( int mask = 1; mask < (1 << K); mask ++ )
    for( int i = 0; i < K; i ++ )
        D[mask][i] = INF;
    D[1][0] = 0;

    for( int i = 1; i < (1 << K); i ++ )
        NrBit[i] = NrBit[i / 2] + (i % 2);

    for( int mask = 1; mask < (1 << K); mask ++ ) {
        for( int i = 0; i < K; i ++ ) {

            if( !((mask >> i) & 1) )
                continue;

            for( int j = 0; j < K; j ++ ) {

                if( ((mask >> j) & 1) )
                    continue;

                if( D[mask + (1 << j)][j] > D[mask][i] + Dist[NrBit[mask]][i][j] )
                    D[mask + (1 << j)][j] = D[mask][i] + Dist[NrBit[mask]][i][j];
            }
        }
    }

    minim = INF;
    for( int i = 1; i < K; i ++ ) {
        if( minim > D[(1 << K) - 1][i] )
            minim = D[(1 << K) - 1][i];
    }

    printf( "%lld\n", minim );

    return 0;
}