Cod sursa(job #1016500)

Utilizator roots4Irimia Alexandru Gabriel roots4 Data 26 octombrie 2013 13:19:42
Problema Gather Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.72 kb
#include<fstream>
#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<utility>
#include<string.h>
#include<functional>

using namespace std;

#define dtp int
#define max_n 760
#define max_k 18
#define max_m 1300
#define inf 1000000000

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];

dtp C[max_m];

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]; Find[K[i]] = i;
    }

    K[++k] = 1; Find[K[k]] = k;

    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 nod , dtp t ){

    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];

    memset( D , 0 , sizeof(D) );
    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 <= n ; i++ ){
        if( Find[i] != 0  ){
            if( D[i] == 0 )
                Dr_min[Find[nod]][Find[i]][t] = inf;
            else
                Dr_min[Find[nod]][Find[i]][t] = D[i];
		}
    }

}

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

void pre_proc(){

    for( dtp i = 1 ; i < (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(K[i] , t);
			//for( int j = 1 ; j <= k ; j++ )
			//	cout<<Dr_min[i][j][t]<<" ";
			//cout<<"\n";
		}
		//cout<<"\n";
	}

}

void solve(){

    dtp i , j;
    dtp p , u;
    dtp nod; bool Fr[max_k];
	memset(Fr , 0 , sizeof(Fr));

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

    Dist[k][0] = 0;
    p = u = 1;
    C[p] = k;

    while( p <= u ){
		
        nod = C[p];Fr[nod] = 0;
		
        for( j = 0 ; j < ( 1<<(k-1) ) ; j++ ){
            if( Dist[nod][j] == inf )
                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(Fr[i] == 0)
                        C[++u] = i , Fr[i] = 1;
                }
                if( i < k && ((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]];
                    if(Fr[i] == 0)
                        C[++u] = i , Fr[i] = 1;
                }
            }
        }
		
        p++;
    }

    dtp sol = inf;

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

int main(){

    read();

    pre_proc();

    solve();

    return 0;
}