Cod sursa(job #115640)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 16 decembrie 2007 18:59:17
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.08 kb
#include <cstdio>
#include <vector>
#include <set>

using namespace std;

#define MAXN 755
#define MAXK 16

int K, N, M;
vector<int> det;

int Min[MAXK][MAXK][MAXN];
int d[MAXN];

vector<int> con[MAXN];
int Cst[MAXN][MAXN], Cap[MAXN][MAXN];

set< pair<int, int> > H;

inline void dijkstra( int S, int d[MAXN], int nrDet )
{
	memset( d, 0x3f, sizeof(int) * MAXN );
	d[S] = 0; H.insert( make_pair( d[S], S ) );

	for (; !H.empty(); )
	{
		int i = (*H.begin()).second;

		H.erase( H.begin() );
		vector<int> :: iterator it;
		for (it = con[i].begin(); it != con[i].end(); it++)
			if (Cap[i][*it] >= nrDet && d[i] + Cst[i][*it] * (nrDet + 1) < d[*it])
			{
				H.erase( make_pair( d[*it], *it ) );
				d[*it] = d[i] + Cst[i][*it] * (nrDet + 1);
				H.insert( make_pair( d[*it], *it ) );
			}
	}
}

int bst[ 1 << MAXK ][MAXK];

int main()
{
	freopen("gather.in", "rt", stdin);
	freopen("gather.out", "wt", stdout);

	scanf("%d %d %d", &K, &N, &M);
	for (int i = 0; i < K; i++)
	{
		int poz;
		scanf("%d", &poz);

		det.push_back(poz);
	}

	for (int i = 0; i < M; i++)
	{
		int X, Y;
		scanf("%d %d", &X, &Y);
		scanf("%d %d", Cst[X] + Y, Cap[X] + Y);

		Cst[Y][X] = Cst[X][Y];
		Cap[Y][X] = Cap[X][Y];

		con[X].push_back(Y);
		con[Y].push_back(X);
	}

	for (size_t k = 0; k < det.size(); k++)
		for (int i = 0; i < K; i++)
			dijkstra( det[k], Min[k][i], i );
	dijkstra( 1, d, 0 );

	memset( bst, 0x3f, sizeof(bst) );
	for (size_t k = 0; k < det.size(); k++)
		bst[ 1 << k ][k] = d[ det[k] ];

	for (int st = 1; st < (1 << det.size()); st++)
		for (size_t k = 0; k < det.size(); k++)
		{
			if (bst[st][k] == 0x3f3f3f3f)
				continue;

			int NR = 0;
			for (size_t a = 0; a < det.size(); a++)
				if (st & (1 << a))
					NR++;

			for (size_t a = 0; a < det.size(); a++)
			{
				if (st & (1 << a)) continue;

				int newVal = bst[st][k] + Min[k][NR][ det[a] ];
				if (newVal < bst[st | (1 << a)][a])
					bst[st | (1 << a)][a] = newVal;
			}
		}

	int MIN = 0x3f3f3f3f;
	for (size_t k = 0; k < det.size(); k++)
		if (bst[ (1 << det.size()) - 1 ][k] < MIN)
			MIN = bst[ (1 << det.size()) - 1 ][k];
	printf("%d\n", MIN);
	return 0;
}