Cod sursa(job #116055)

Utilizator MariusMarius Stroe Marius Data 17 decembrie 2007 18:36:44
Problema Gather Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.3 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <memory.h>

using namespace std;

const char iname[] = "gather.in";
const char oname[] = "gather.out";

typedef unsigned int uint;

#define MAXK  16
#define MAXSTATE  1 << MAXK
#define MAXN  755
#define INF   (uint)4294967294

int K, N, M;

uint C[MAXSTATE][MAXK];  int P[MAXK + 1];

struct tlist_node {
	int nod;
	uint cst, cap;
	void update(int nod, uint cst, uint cap) {
		this->nod = nod;
		this->cst = cst;
		this->cap = cap;
	}
} ;

vector <tlist_node> G[MAXN];

uint dist[MAXK][MAXK];


void BellmanFord(int k, int s, uint cnt)
{
	queue <int> Q;
	vector <uint> tdist(N + 1, INF);

	vector <tlist_node>::iterator it;

	tdist[s] = 0;
	for (Q.push(s); !Q.empty(); )
	{
		int x = Q.front();
		Q.pop();
		for (it = G[x].begin(); it != G[x].end(); ++ it) if (it->cap >= cnt)
			if (tdist[it->nod] > tdist[x] + it->cst) {
				tdist[it->nod] = tdist[x] + it->cst;
				Q.push(it->nod);
			}
	}
	for (int i = 0; i < K; ++ i)
		dist[k][i] = tdist[P[i]]; 
}		

uint g(int s, int p)
{
	if (C[s][p] != -1)	return C[s][p];

	if (s & (s - 1)) 
	{	// sunt cel putin doi detinuti
		int cnt = 0;
		for (int i = 0; i < K; ++ i) if ((s >> i) & 1)
			cnt ++;
		int t = s ^ (1 << p);
		for (int i = 0; i < K; ++ i) if ((t >> i) & 1)
		{
			uint res = g(t, i) + (uint)cnt * dist[i][p];
			if (C[s][p] > res)
				C[s][p] = res;
		}
	} else
		C[s][p] = dist[K][p];

	return C[s][p];
}

void f(int s, int k, int n)
{
	if (n == 0) {
		for (int i = 0; i < K; ++ i) if ((s >> i) & 1)
			g(s, i);
	} else {
		if (K - k > n)
			f(s, k + 1, n);
		f(s | (1 << k), k + 1, n - 1);
	}
}

int main(void)
{
	freopen(iname, "r", stdin);
	freopen(oname, "w", stdout);

	int x, y, cst, cap;
	
	scanf("%d %d %d", &K, &N, &M);
	for (int i = 0; i < K; ++ i)
		scanf("%d", &P[i]);
	tlist_node t;
	for (int i = 0; i < M; ++ i) {
		scanf("%d %d %u %u", &x, &y, &cst, &cap);
		t.update(y, cst, cap);
		G[x].push_back(t);
		t.update(x, cst, cap);
		G[y].push_back(t);
	}
	for (int i = 0; i < MAXSTATE; ++ i)
		for (int j = 0; j < MAXK; ++ j)	  C[i][j] = INF;

	P[K] = 1;
	for (int i = 1; i <= K; ++ i) {
		for (int j = 0; j <= K; ++ j)
			BellmanFord(j, P[j], (uint)i - 1);
		f(0, 0, i);
	}

	uint ans = INF;
	for (int i = 0; i < K; ++ i) {
		if (ans > C[(1 << K) - 1][i])
			ans = C[(1 << K) - 1][i];
	}
	printf("%u\n", ans);

	return 0;
}