Cod sursa(job #489005)

Utilizator ProtomanAndrei Purice Protoman Data 30 septembrie 2010 18:44:22
Problema Gather Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <set>

#define MAX 1024
#define ll long long
#define pb push_back
#define mp make_pair
#define f first
#define s second
#define INF 1000000000000000000LL

using namespace std;

ll k, n, m, nrDet;
ll vctDist[MAX];
vector <int> det;
vector <pair <pair <ll, ll>, ll> > vctDrum[MAX];
ll sol[1 << 17][17];
ll dist[17][17][17];
set <pair <ll, ll> > minHeap;

inline void dijkstra(int source)
{
	for (int i = 1; i <= n; i++)
		vctDist[i] = INF;
	vctDist[source] = 0;
	minHeap.insert(mp(0, source));

	for (; minHeap.size(); )
		if (minHeap.begin()->f == vctDist[minHeap.begin()->s])
		{
			int nod = minHeap.begin()->s;
			minHeap.erase(minHeap.begin());

			for (int i = 0; i < vctDrum[nod].size(); i++)
				if (vctDrum[nod][i].s >= nrDet && vctDist[nod] + vctDrum[nod][i].f.s < vctDist[vctDrum[nod][i].f.f])
				{
					minHeap.erase(mp(-vctDist[vctDrum[nod][i].f.f], vctDrum[nod][i].f.f));

					vctDist[vctDrum[nod][i].f.f] = vctDist[nod] + vctDrum[nod][i].f.s;
					minHeap.insert(mp(-vctDist[vctDrum[nod][i].f.f], vctDrum[nod][i].f.f));
				}
		}
		else minHeap.erase(minHeap.begin());
}

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

	scanf("%lld %lld %lld\n", &k, &n, &m);

	for (; k; k--)
	{
		int x;
		scanf("%d\n", &x);

		det.pb(x);
	}
	for (int i = 0; i < (1 << det.size()); i++)
		for (int j = 0; j < det.size(); j++)
			sol[i][j] = INF;

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

		vctDrum[n1].pb(mp(mp(n2, c), d));
		vctDrum[n2].pb(mp(mp(n1, c), d));
	}

	for (nrDet = det.size() + 1; nrDet >= 0; nrDet--)
		for (int i = 0; i < det.size(); i++)
		{
			dijkstra((int) det[i]);

			for (int j = 0; j < det.size(); j++)
				dist[nrDet][i][j] = (nrDet + 1) * vctDist[det[j]];
		}

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

	for (int conf = 1; conf < (1 << det.size()); conf++)
		for (int ult = 0; ult < det.size(); ult++)
			if (sol[conf][ult] != INF && (conf & (1 << ult)))
			{
				nrDet = 0;
				for (int j = conf; j; nrDet++, j &= (j - 1));

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

	ll minGs = INF;
	for (int i = 0; i < det.size(); i++)
		minGs = min(minGs, sol[(1 << det.size()) - 1][i]);

	if (minGs == INF)
		for (; ; );

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

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