Cod sursa(job #116023)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 17 decembrie 2007 17:07:51
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.27 kb
// O( K*N*M + K^2 * 2^K )
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>

using namespace std;

#define PB push_back

const long long INF = 0x3f3f3f3f3f3f3f3fLL;
const int NMAX = 1024;
const int KMAX = 16;

struct edge {
	int v;
	unsigned c, d;
	edge(int _v = 0, unsigned _c = 0, unsigned _d = 0) : v(_v), c(_c), d(_d) {}
	bool operator<(const edge &a) const {
		return d > a.d;
	}
};

int K, N, M;
int P[KMAX];
vector <edge> G[NMAX];
long long Dist[KMAX][KMAX][KMAX];
bool B[KMAX][1 << KMAX];
long long O[KMAX][1 << KMAX];

void read(void) {
	FILE *fin = fopen("gather.in", "rt");
	int i, a, b;
	unsigned c ,d;

	fscanf(fin, " %d %d %d", &K, &N, &M);

	for (i = 0; i < K; ++i)
		fscanf(fin, " %d", &P[i]);

	for (i = 0; i < M; ++i) {
		fscanf(fin, " %d %d %u %u", &a, &b, &c, &d);

		G[a].PB( edge(b, c, d) );
		G[b].PB( edge(a, c, d) );
	}

	fclose(fin);
}

void bellmanFord(void) {
	int i, j, k, u;
	vector <edge> :: iterator it;
	bool V[NMAX];
	long long D[NMAX];
	queue <int> Q;

	for (i = 1; i <= N; ++i)
		sort(G[i].begin(), G[i].end());

	P[K] = 1;
	for (i = 0; i <= K; ++i) {
		
		memset(D, 0x3f, sizeof(D));

		D[P[i]] = 0;

		for (j = K; j >= 0; --j) {
			
			for (k = 1; k <= N; ++k)
				V[k] = true,
				Q.push(k);

			for (; !Q.empty(); Q.pop()) {
				u = Q.front();
				V[u] = false;

				for (it = G[u].begin(); it != G[u].end() && it->d >= (unsigned)j; ++it) {
					if (D[u] + it->c >= D[it->v])
						continue;
					D[it->v] = D[u] + it->c;

					if (V[it->v] == true)
						continue;

					V[it->v] = true;
					Q.push(it->v);

				}
			}

			for (k = 0; k < K; ++k) {
				if (D[P[k]] * (j + 1))
					Dist[j][i][k] = D[P[k]] * (j + 1);
			}
		}

	}
}

long long solve(int k, int cnf, int mlt) {
	if (mlt == 0)
		return Dist[0][K][k];
	if (B[k][cnf] == true)
		return O[k][cnf];
	
	int i;
	long long rez = INF, t;

	for (i = 0; i < K; ++i)
		if (cnf & (1 << i)) {
			t = solve(i, cnf & ~(1 << i), mlt - 1);
			t += Dist[mlt][k][i];
			rez = min(rez, t);
		}

	B[k][cnf] = true;
	return O[k][cnf] = rez;
}

void write(void) {
	FILE *fout = fopen("gather.out", "wt");
	int i;
	long long rez;

	for (i = 0; i < K; ++i)
		rez = min(rez, solve(i, (1 << K) - 1, K));

	fprintf(fout, "%lld\n", rez);

	fclose(fout);
}

int main(void) {

	read();

	bellmanFord();

	write();

	return 0;
}