Cod sursa(job #191945)

Utilizator andrei.12Andrei Parvu andrei.12 Data 29 mai 2008 21:40:31
Problema Gather Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.26 kb
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;

#define pb push_back
#define lg 760
#define lint long long

int k, n, m, i, det[17], x, y, cst, cp, nrt, nod, j, cnt[lg], pt[17], nr, str, nxt, h, t;
bool fst[lg];
lint a[17][17][17], d[38000][17], raspuns, infinit = 2000000000000LL;

struct ches{
	int v, c, cp;
};
ches vvs;
vector<ches> v[lg];
vector<int> pz[17];
queue<int> q;

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

	scanf("%d%d%d", &k, &n, &m);
	for (i = 1; i <= k; i ++)
		scanf("%d", &det[i]);
	det[k+1] = 1;
	for (i = 1; i <= m; i ++){
		scanf("%d%d%d%d", &x, &y, &cst, &cp);

		vvs.v = y, vvs.c = cst, vvs.cp = cp;
		v[x].pb(vvs);

		vvs.v = x;
		v[y].pb(vvs);
	}

	for (nrt = 0; nrt <= k; nrt ++)
		for (i = 1; i <= k+1; i ++){
			nod = det[i];

			q.push(nod);
			memset(cnt, 0x3f, sizeof(cnt)), memset(fst, 0, sizeof(fst));
			fst[nod] = 1, cnt[nod] = 0;

			while (!q.empty()){
				nod = q.front(), q.pop();

				for (j = 0; j < v[nod].size(); j ++)
					if (v[nod][j].cp >= nrt && cnt[nod] + v[nod][j].c < cnt[v[nod][j].v]){
						cnt[v[nod][j].v] = cnt[nod] + v[nod][j].c;

						if (!fst[v[nod][j].v]){
							fst[v[nod][j].v] = 1;
							q.push(v[nod][j].v);
						}
					}
			}
			for (j = 1; j <= k; j ++)
				a[nrt][i][j] = cnt[det[j]];
		}
	/*
	for (nrt = 0; nrt <= k; nrt ++)
		for (i = 1; i <= k+1; i ++)
			for (j = 1; j <= k; j ++)
				printf("de la %d la %d cu %d detinuti -> %d\n", det[i], det[j], nrt, a[nrt][i][j]);
	*/
	pt[1] = 1;
	for (i = 2; i <= k; i ++)
		pt[i] = 2*pt[i-1];

	for (i = 1; i < (1 << k); i ++){
		j = i, nr = 0;

		while (j){
			if (j % 2 == 1)
				nr ++;
			j /= 2;
		}

		pz[nr].pb(i);
	}
	
	memset(d, 0x3f, sizeof(d));
	for (i = 1; i <= k; i ++){
		nod = pt[i];
		
		d[nod][i] = a[0][k+1][i];
	}

	raspuns = infinit;
	for (i = 1; i <= k; i ++)
		for (j = 0; j < pz[i].size(); j ++){
			str = pz[i][j];

			for (h = 1; h <= k; h ++)
				if (d[str][h] != infinit){
					for (t = 1; t <= k; t ++)
						if (!(str & pt[t])){
							nxt = str | pt[t];

							if (d[str][h] + (i+1)*a[i][h][t] < d[nxt][t])
								d[nxt][t] = d[str][h] + (i+1)*a[i][h][t];
						}

				if (i == k)
					raspuns = min(raspuns, d[str][h]);
				}
		}

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

	return 0;
}