Cod sursa(job #810893)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 11 noiembrie 2012 10:59:19
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.88 kb
#include<stdio.h>
#include<vector>
#include<queue>

#define maxk 17
#define maxn 755
#define pb push_back
#define mp make_pair

using namespace std;

FILE*f=fopen("gather.in","r");
FILE*g=fopen("gather.out","w");

const long long inf = (1LL<<62);

int k,n,m;
int where[maxk],which[maxn],T[maxn],biti[1<<(maxk-2)];
long long D[maxk][maxk][maxn],best[maxk][1<<(maxk-2)];
queue<int>Q; int inQ[maxn];
vector< pair<int, pair<long long,int> > >G[maxn];

inline void citire () {
	
	fscanf(f,"%d %d %d",&k,&n,&m);
	for ( int i = 1 ; i <= k ; ++i ){
		fscanf(f,"%d",&where[i]);
		which[where[i]] = i;
	}
	int x,y; long long cost,lim;
	for ( int i = 1 ; i <= m ; ++i ){
		fscanf(f,"%d %d %lld %lld",&x,&y,&cost,&lim);
		if ( lim > 20 )	lim = 20;
		G[x].pb(mp(y,mp(cost,lim)));
		G[y].pb(mp(x,mp(cost,lim)));
	}
}

inline void bf ( int start , int nr , long long *dist ){
	
	for ( int i = 1 ; i <= n ; ++i ){
		dist[i] = inf;
		T[i] = 0;
	}
	
	dist[start] = 0;
	Q.push(start); inQ[start] = 1;
	while ( !Q.empty() ){
		int nod = Q.front(); Q.pop(); inQ[nod] = 0;
		if ( inQ[ T[nod] ] )	continue ;
		
		for ( vector< pair<int, pair<long long,int> > >::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
			int vecin = itt->first;
			long long cost = itt->second.first;
			int lim_here = itt->second.second;
			
			if ( lim_here >= nr ){
				if ( dist[vecin] > dist[nod] + 1LL*cost*(nr+1) ){
					dist[vecin] = dist[nod] + 1LL*cost*(nr+1);
					T[vecin] = nod;
					if ( !inQ[vecin] ){
						Q.push(vecin); inQ[vecin] = 1;
					}
				}
			}
		}
	}
}

inline void get_shortest () {
	
	for ( int i = 1 ; i <= k ; ++i ){
		for ( int nr = 0 ; nr <= k ; ++nr ){
			bf(where[i],nr,D[i][nr]);
		}
	}
	bf(1,0,D[0][0]);
}

inline void compute_biti () {
	
	for ( int i = 1 ; i < (1<<k) ; ++i ){
		
		int conf = i;
		while ( conf ){
			++biti[i];
			conf &= (conf-1);
		}
	}
}

inline void solve () {
	
	for ( int i = 1 ; i <= k ; ++i ){
		for ( int j = 0 ; j < (1<<k) ; ++j ){
			best[i][j] = inf;
		}
	}
	
	compute_biti();
	
	best[0][0] = 0;
	for ( int conf = 0 ; conf < (1<<k) ; ++conf ){
		for ( int nod = (conf != 0) ; nod <= k ; ++nod ){
			
			int next_conf = conf;
			if ( nod ){
				next_conf |= (1<<(nod-1));
			}
			else{
				if ( which[1] ){
					next_conf |= (1<<(which[1]-1));
				}
			}
			
			for ( int next = 1 ; next <= k ; ++next ){
				
				if ( best[next][next_conf] > best[nod][conf] + D[nod][ biti[next_conf] ][where[next]] ){
					best[next][next_conf] = best[nod][conf] + D[nod][ biti[next_conf] ][where[next]];
				}
			}
		}
	}
	
	long long sol = inf;
	for ( int nod = 1 ; nod <= k ; ++nod ){
		if ( best[nod][(1<<k)-1] < sol ){
			sol = best[nod][(1<<k)-1];
		}
	}
	
	fprintf(g,"%lld\n",sol);
}

int main () {
	
	citire();
	get_shortest();
	solve();
	
	fclose(f);
	fclose(g);
	
	return 0;
}