Cod sursa(job #115491)

Utilizator alextheroTandrau Alexandru alexthero Data 16 decembrie 2007 12:50:27
Problema Gather Scor 70
Compilator cpp Status done
Runda preONI 2008, Runda 2, Clasele 11-12 Marime 3.23 kb
#include <stdio.h>
#include <vector>
#include <queue>

#define cp second.second
#define cost second.first
#define min(i,j) ((i) > (j) ? (j) : (i))
#define kmax 17
#define nmax 800
#define pb push_back
#define confmax 32768

using namespace std;
typedef pair<int, long long> iu;
typedef pair<int, int> ii;
typedef pair<long long, int> ui;
typedef pair<int, ui> iui;
typedef pair<long long, pair<int, int> > uii;

long long inf, cs;
ui aux;
uii aux1;
int k, n, m, n1, n2, cap, config, newconf, copie, cate1;
int nd[kmax], inv[nmax];
vector <iui> e[nmax];
vector <int> det[nmax];
vector <ii> ng[nmax][nmax];
long long a[nmax], newcost;
long long d[kmax][confmax];

long long dijkstra1()
{
	priority_queue <uii, vector <uii>, greater <uii> > Q;
	for(int i = 1; i <= nd[0]; i++)
		for(int j = 0; j < confmax; j++)
			d[i][j] = inf;

	d[1][0] = 0;
	Q.push(uii(0, ii(1, 0)));
	while(!Q.empty())
	{
		aux1 = Q.top();
		Q.pop();
		n1 = aux1.second.first;
		config = aux1.second.second;
		if(d[n1][config] == aux1.first)
		{
			copie = config;
			cate1 = 0;
			do {
				cate1 += copie % 2;
				copie /= 2;
			} while(copie);

			if(cate1 == k) return aux1.first;
	
			for(int i = 0; i < (int)det[nd[n1]].size(); i++)
			{
				newconf = config | (1 << (det[nd[n1]][i] - 1));
				if(d[n1][config] < d[n1][newconf])
				{
					d[n1][newconf] = d[n1][config];
					Q.push(uii(d[n1][newconf], ii(n1, newconf)));
				}
			}

			for(int i = 0; i < (int)ng[n1][cate1].size(); i++)
			{
				if((long long)d[n1][config] + ng[n1][cate1][i].second * (cate1 + 1) > inf) continue;
				if((long long)d[n1][config] + ng[n1][cate1][i].second * (cate1 + 1) < d[ng[n1][cate1][i].first][config])
				{
					d[ng[n1][cate1][i].first][config] = (long long)d[n1][config] + ng[n1][cate1][i].second * (cate1 + 1);
					Q.push(uii(d[ng[n1][cate1][i].first][config], ii(ng[n1][cate1][i].first, config)));
				}
			}
		}
	}

	return inf;
}

void dijkstra(int nod, int cap)
{
	priority_queue <ui, vector <ui>, greater <ui> > Q;
	for(int i = 0; i <= n; i++) a[i] = inf;
	a[nod] = 0;

	Q.push(ui(0, nod));
	while(!Q.empty())
	{
		aux = Q.top();
		Q.pop();
		n1 = aux.second;
		if(a[n1] == aux.first)
		{
			for(int i = 0; i < (int)e[n1].size(); i++)
				if(e[n1][i].cp >= cap)
				{
					n2 = e[n1][i].first;
					if((long long)a[n1] + e[n1][i].cost > inf) continue;
					newcost = (long long)a[n1] + e[n1][i].cost;
					if(newcost < a[n2])
					{
						a[n2] = newcost;
						Q.push(ii(newcost, n2));
					}
				}
		}
	}
}

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

	inf = 1 << 31 - 1;
	inf = (long long)inf * 4;
	scanf("%d%d%d", &k, &n, &m);
	for(int i = 1; i <= k; i++)
	{
		scanf("%d", &n1);
		det[n1].pb(i);
	}

	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d%Ld%d", &n1, &n2, &cs, &cap);
		cap = min(cap, k);
		e[n1].pb(iui(n2, ui(cs, cap)));
		e[n2].pb(iui(n1, ui(cs, cap)));
	}

	for(int i = 1; i <= n; i++)
		if(i == 1 || det[i].size() > 0) 
		{
			nd[++nd[0]] = i;
			inv[i] = nd[0];
		}


	for(int i = 1; i <= n; i++)
		if(i == 1 || det[i].size() > 0)
			for(int l = 0; l <= k; l++) 
			{
				dijkstra(i, l);
				for(int j = 1; j <= n; j++)
					if(j == 1 || det[j].size() > 0)
						if(a[j] != inf)
							ng[inv[i]][l].pb(ii(inv[j], a[j]));
			}

	printf("%Ld\n", dijkstra1());

	return 0;
}