Cod sursa(job #488508)

Utilizator ProtomanAndrei Purice Protoman Data 28 septembrie 2010 23:14:30
Problema Gather Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.25 kb
#include <algorithm>
#include <stdio.h>
#include <vector>

#define MAX 1500
#define INF 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define f first
#define s second

using namespace std;

int k, n, m, dimHeap;
int vctDist[MAX], poz[MAX], minHeap[MAX], det[MAX];
vector <pair <int, int> > vctDrum[MAX];
vector <pair <pair <int, int>, int> > vctMuchie[16];
int sol[65000][17];
int dist[32][32][32];

inline void heapUp(int nod)
{
	if (nod == 1)
		return;
	if (vctDist[minHeap[nod]] < vctDist[minHeap[nod / 2]])
	{
		swap(minHeap[nod], minHeap[nod / 2]);
		swap(poz[minHeap[nod]], poz[minHeap[nod / 2]]);

		heapUp(nod / 2);
	}
}

inline void heapDown(int nod)
{
	if (nod * 2 <= dimHeap)
	{
		int l = 2 * nod;
		if (nod * 2 < dimHeap && vctDist[minHeap[l + 1]] < vctDist[minHeap[l]])
			l++;

		if (vctDist[minHeap[nod]] < vctDist[minHeap[l]])
		{
			swap(minHeap[nod], minHeap[l]);
			swap(poz[minHeap[nod]], poz[minHeap[l]]);

			heapDown(l);
		}
	}
}

inline void dijkstra(int source)
{
	dimHeap = n;
	memset(poz, 0, sizeof(poz));
	for (int i = 1; i <= n; i++)
	{
		vctDist[i] = INF;

		minHeap[i] = i;
		poz[i] = i;
	}
	vctDist[source] = 0;
	heapUp(source);

	for (int p = n; p; p--)
	{
		int nod = minHeap[1];
		poz[nod] = 1;
		minHeap[1] = minHeap[dimHeap--];
		heapDown(1);

		if (vctDist[nod] == INF)
			return;

		for (int i = 0; i < vctDrum[nod].size(); i++)
			if (vctDist[nod] + vctDrum[nod][i].s < vctDist[vctDrum[nod][i].f])
			{
				vctDist[vctDrum[nod][i].f] = vctDist[nod] + vctDrum[nod][i].s;
				heapUp(poz[vctDrum[nod][i].f]);
			}
	}
}

inline void addMuchii(int nrDet)
{
	for (int i = 0; i < vctMuchie[nrDet].size(); i++)
	{
		int n1 = vctMuchie[nrDet][i].f.f, n2 = vctMuchie[nrDet][i].f.s, c = vctMuchie[nrDet][i].s;
		
		vctDrum[n1].pb(mp(n2, c));
		vctDrum[n2].pb(mp(n1, c));
	}
}	

int main()
{
	freopen("gather.in", "r", stdin);
	freopen("gather.out", "w", stdout);

	scanf("%d %d %d", &k, &n, &m);

	for (int i = 0; i < k; i++)
		scanf("%d\n", &det[i]);

	for (int i = 1; i <= m; i++)
	{
		int n1, n2, c, d;
		scanf("%d %d %d %d", &n1, &n2, &c, &d);

		vctMuchie[d].pb(mp(mp(n1, n2), c));
		if (d > k)
			for (; ; );
	}

	for (int nrDet = 15; nrDet; nrDet--)
	{
		addMuchii(nrDet);

		for (int i = 0; i < k; i++)
		{
			dijkstra(det[i]);

			for (int j = 0; j < k; j++)
				dist[nrDet][i][j] = vctDist[det[j]];
		}
	}

	addMuchii(0);
	dijkstra(1);
	for (int i = 1; i < (1 << k); i++)
		for (int j = 0; j < k; j++)
			sol[i][j] = INF;

	for (int i = 0; i < k; i++)
		sol[1 << i][i] = vctDist[det[i]];

	for (int conf = 1; conf < (1 << k); conf++)
	{
		for (int ult = 0; ult < k; ult++)
			if (conf & (1 << ult))
			{
				int nrDet = 0;
				for (int i = 0; i < k; i++)
					nrDet += (bool) (conf & (1 << i));

				for (int nou = 0; nou < k; nou++)
					if (!(conf & (1 << nou)) && sol[conf][ult] != INF && dist[nrDet][ult][nou] != INF)
						sol[conf | (1 << nou)][nou] = min(sol[conf | (1 << nou)][nou], sol[conf][ult] + dist[nrDet][ult][nou] * (nrDet + 1));
			}
	}

	int minGs = INF;
	for (int i = 0; i < k; i++)
		minGs = min(minGs, sol[(1 << k) - 1][i]);

	printf("%d\n", minGs);

	fclose(stdin);
	fclose(stdout);
	return 0;
}