Cod sursa(job #303223)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 9 aprilie 2009 17:37:11
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.24 kb
using namespace std;

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <utility>
#include <functional>

#define pb push_back
#define nod first
#define f first
#define s second
#define cs second.first
#define cp second.second
#define sz size
#define II inline
#define ll long long
#define db double
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define all(v) v.begin() , v.end()
#define C(v) C.erase( all(v) )
#define FORit(it,v) for(it = (v).begin();it != (v).end();++it)
#define mp make_pair

#define IN "gather.in"
#define OUT "gather.out"
#define K_MAX 1<<4
#define N_MAX 1<<11
#define oo 1684300900

typedef vector<int> VI;
vector< vector< pair< int , pair<int,int> > > > A(N_MAX);
int E[K_MAX][K_MAX][K_MAX];
int S[N_MAX],stv[N_MAX],N,K,M;
vector<bool> D(N_MAX);
int C[1<<(K_MAX)][K_MAX];

II int get_bit(int x)
{
	bitset<16> bit = x;
	return int(bit.count());
}

II void scan()
{
	int x,y,c,cc;
	freopen(IN,"r",stdin);
	freopen(OUT,"w",stdout);
	scanf("%d%d%d\n",&K,&N,&M);
	
	FOR(i,1,K)
		scanf("%d",&stv[i]),
		D[stv[i]] = true;
	FOR(i,1,M)
	{
		scanf("%d%d%d%d\n",&x,&y,&c,&cc);
		A[x].pb( mp(y, mp(c,cc) ) );
		A[y].pb( mp(x, mp(c,cc) ) );
	}
}

priority_queue< pair<int,int> ,vector<pair<int,int> >, greater<pair<int,int> > > Q;

II void dijkastra(int cost,int SS)
{
	memset(S,100,sizeof(S));
	
	S[stv[SS] ] = 0;
	Q.push( mp(stv[SS],0) );
	
	for(;!Q.empty();)
	{
		int nod = Q.top().f;
		int dist  = Q.top().s;
		
		Q.pop();
		if(dist > S[nod])
			continue;
		
		int l = A[nod].sz() - 1;
		FOR(i,0,l)
		{
			int next = A[nod][i].nod;
			if(S[next] > S[nod] + A[nod][i].cs && A[nod][i].cp >= cost)
			{
				S[next] = S[nod] + A[nod][i].cs;
				if(S[next]  < 0)
				{
					S[next] = oo;
					continue;
				}	
				Q.push( mp(next,S[next]) );
			}	
		}
	}	
	FOR(i,1,K)
		if(i != SS)
			E[cost][SS][i] = S[ stv[i] ];
}

II void find_edges()
{
	memset(E,100,sizeof(E));
	
	FOR(i,1,K)
	FOR(n,1,K)
		dijkastra(i,n);
	stv[ K+1 ] = 1;	
	dijkastra(0,K+1);	
}

II void afis(int x)
{
	for(;x;x >>= 1)
		if(x & 1)
			printf("1");
		else
			printf("0");
}

II void solve()
{
	memset(C,100,sizeof(C));
	
	FOR(i,1,K)
		C[0][i] = E[0][K+1][i];
	if(D[1] == true)
		C[0][1] = 0;

	FOR(k,0,(1<<K)-1)
	FOR(ii,1,K)
	{
		int nr_bit = get_bit(k)+1;
		if(C[k][ii] == oo)
			continue;
		//printf("din %d cu costul %d si %d detinuti \n",stv[ii],C[k][ii],nr_bit-1);
		FOR(i,1,K)
		{
			if(i == ii)
				continue;
			if(E[ nr_bit ][ii][i] != oo && !(k & (1<<(i-1))) )
			{
				C[k + (1<<(ii-1)) ][i] = min(C[k + (1<<(ii-1)) ][i] , C[k][ii] + E[ nr_bit ][ii][i] * (nr_bit+1) );
				//printf("mergem in %d cu costul %d si cu %d detinuti  ** ",stv[i],C[k + (1<<(ii-1)) ][i],nr_bit);
				//afis( k + (1<<(ii-1))  );
				//printf("\n");
			}	
		}	
	}

	int rez(oo);
	FOR(i,(1<<(K-1))-1,(1<<K)-1)
		if(get_bit(i) ==  K-1)
			FOR(j,1,K)
				if(get_bit(i | (1<<(j-1)) ) == K) 
					rez = min(rez, C[i][j]);
	
	printf("%d\n",rez);	
}

int main()
{
	scan();
	find_edges();
	solve();
	return 0;
}