Cod sursa(job #1704615)

Utilizator sucureiSucureiRobert sucurei Data 19 mai 2016 09:44:43
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.21 kb
#include<fstream>
#include<vector>
#include<queue>
#include<utility>
#include<string.h>
#include<functional>

using namespace std;

#define dtp unsigned int
#define max_n 760
#define max_k 18
#define max_m 1300

const dtp inf = 4000000000;


ifstream f("gather.in");
ofstream g("gather.out");

dtp k , n , m;

dtp K[max_k] , Find[max_n];

dtp Dr_min[max_k][max_k][max_k] , P[1<<17] , Dist[max_k][1<<17];

struct nd{
    dtp next , dist , cap;
};

vector<nd> L[max_n];

void read(){

    nd nod;
    dtp x , y;

    f>>k>>n>>m;

    for( dtp i = 1 ; i <= k ; i++ ){
        f>>K[i];
    }

    K[0] = 1;

    for( dtp i = 1 ; i <= m ; i++ ){
        f>>x>>y>>nod.dist>>nod.cap;
        nod.next = y;
        L[x].push_back(nod);
        nod.next = x;
        L[y].push_back(nod);
    }

}

void dijkstra( dtp ind , dtp t ){

    dtp nod = K[ind];

    pair<dtp , dtp> node;

    priority_queue< pair< dtp , dtp > , vector< pair<dtp , dtp> > , greater< pair<dtp , dtp> >  > S;

    bool Viz[max_n];
    dtp i , D[max_n];

    for( i = 1 ; i <= n ; i++ )
        D[i] = inf;

    memset( Viz , 0 , sizeof(Viz) );

    S.push( make_pair(0 , nod) );

    while( !S.empty() ){

        node = S.top();
        S.pop();

        if( Viz[ node.second ] )
            continue;

        D[node.second] = node.first;
        Viz[node.second] = true;

        for( i = 0 ; i < L[node.second].size() ; i++ ){
            if( Viz[L[node.second][i].next] == 0 && L[node.second][i].cap >= t ){
                S.push( make_pair( node.first + L[node.second][i].dist , L[node.second][i].next ) );
            }
        }

    }

    for( i = 1 ; i <= k ; i++ )
        Dr_min[ind][i][t] = D[K[i]];

}

dtp minim( dtp a , dtp b ){
    if( a < b )
        return a;
    return b;
}

void pre_proc(){

    for( dtp i = 1 ; i < (dtp)(1<<k) ; i++ )
        P[i] = P[i/2] + i%2;

    for( dtp t , i = 1 ; i <= k ; i++ )
        for( t = 0 ; t <= k ; t++ )
            dijkstra(i , t);

    dijkstra( 0 , 0 );

}

void solve(){

    dtp i , j;
    dtp nod;

    for( i = 1 ; i <= k ; i++ )
        for( j = 0 ; j < (dtp)(1 << k) ; j++ )
            Dist[i][j] = inf;

    Dist[0][0] = 0;

    for( j = 0 ; j < (dtp)(1<<k) ; j++ ){
        for( nod = 0 ; nod <= k ; nod++ ){
            if( j != 0 && nod == 0 )
                continue;
            for( i = 1 ; i <= k ; i++ ){
                if( nod == i )
                    continue;
                if( Dr_min[nod][i][P[j]] == inf )
                    continue;
                if( Dist[i][j] > Dist[nod][j] + (P[j]+1)*Dr_min[nod][i][P[j]] ){
                    Dist[i][j] = Dist[nod][j] + (P[j]+1)*Dr_min[nod][i][P[j]];
                }
                if( i > 0 && ((1<<(i-1))&j) == 0 && Dist[i][j|(1<<(i-1))] > Dist[nod][j] + (P[j]+1)*Dr_min[nod][i][P[j]] ){
                    Dist[i][j|(1<<(i-1))] = Dist[nod][j] + (P[j]+1)*Dr_min[nod][i][P[j]];
                }
            }
        }
    }

    dtp sol = inf;

    for( i = 1 ; i <= k ; i++ )
        sol = minim(sol , Dist[i][(1<<k)-1]);
    g<<sol<<"\n";
}

int main(){

    read();

    pre_proc();

    solve();

    return 0;
}