Cod sursa(job #220239)

Utilizator Data 9 noiembrie 2008 21:55:53
Problema Gather Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.3 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 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 1<<30

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)][N_MAX];

II int get_bit(int x)
{
	bitset<32> 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) ) );
	}
}

struct Comp
{ 
	bool operator() (int i,int j) 
	{ 
		return S[i] > S[j];
	}
};	
priority_queue<int, VI, Comp> Q;

II void dijkastra(int cost,int SS)
{
	int NR[N_MAX];
	bool viz[N_MAX];
	
	memset(S,100,sizeof(S));
	memset(viz,0,sizeof(viz));
	memset(NR,0,sizeof(NR));
	
	S[stv[SS] ] = 0;
	Q.push(stv[SS]);
	++NR[ stv[SS] ];
	
	for(int nod;!Q.empty();)
	{
		nod = Q.top();
		Q.pop();
		--NR[nod];
		if(viz[nod] || NR[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;
				++NR[next];
				Q.push(next);
			}	
		}
	}	
	FOR(i,1,K)
		if(i != SS)
			E[cost][SS][i] = S[ stv[i] ];
}

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

II void solve()
{
	memset(C,50,sizeof(C));
	
	FOR(i,1,K)
		C[0][i] = E[0][K+1][i];
	if(D[1] == true)
		C[0][1] = 0;
/*		
	FOR(k,1,K)
	{
		printf("Cu capacitate %d \n",k);
		
		FOR(i,1,K)
		{
			FOR(j,1,K)
				if(i!=j)
					printf("din %d in %d cu %d\n",stv[i],stv[j],E[k][i][j]);
			printf("\n");
		}
		printf("\n");
	}	
*/	
	FOR(k,0,(1<<K)-1)
	FOR(ii,1,K)
	{
		//int nod = stv[ii];
		int nr_bit = get_bit(k)+1;
		if(nr_bit + 1 > K)
			continue;
		//printf("\ndin %d cost %d pentru %d detinuti\n",stv[ii],C[k][ii],nr_bit-1);
		FOR(i,1,K)
		{
			//int next = stv[i];
			if(i == ii)
				continue;
			if(E[ nr_bit ][ii][i] != oo && !(k & (1<<(i-1))) )
				C[k + (1<<(i-1)) ][i] = min(C[k + (1<<(i-1)) ][i] , C[k][ii] + E[ nr_bit ][ii][i] * (nr_bit+1) );
			//printf("putem ajunge in %d cu %d detinuti cu costul %d pe %d\n",stv[i],nr_bit, C[k + (1<<(i-1))][i] ,k+(1<<(i-1)) );
		}	
	}

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

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