Cod sursa(job #1488707)

Utilizator theprdvtheprdv theprdv Data 19 septembrie 2015 16:27:44
Problema Gather Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.93 kb
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define MAXN 752
#define foreach(V) for (::node *it = (V); it; it = it->link)
#define MIN(x, y) ( ((x) < (y)) ? (x) : (y) )

int N, M, K, __K[16];
unsigned int __dist[MAXN];
short int __bitset[MAXN];
bool mode[MAXN];

struct node{
	short int next;
	char cnt;
	int cost;
	node *link;
} *G[MAXN];

int heap_size;
struct heap_elem{
	short int bitset, node;
	unsigned int cost;
	char cnt;
} Heap[1 << 13];

inline char nth_k(short int val){
	for (int i = 0; __K[i]; ++i) if (__K[i] == val) return i;
	return -1;
}

void pop(){
	Heap[1] = Heap[heap_size--];
	heap_elem now = Heap[1];
	
	int next = 2;
	if (next + 1 <= heap_size && Heap[next + 1].cost < Heap[next].cost) ++next;

	while (next <= heap_size && Heap[next].cost < now.cost){
		Heap[next >> 1] = Heap[next];
		next <<= 1;
		if (next + 1 <= heap_size && Heap[next + 1].cost < Heap[next].cost) ++next;
	}
	Heap[next >> 1] = now;
}

void insert(short int node, unsigned int cost, short int used, char cnt){
	Heap[++heap_size].node = node;
	Heap[heap_size].cost = cost;
	Heap[heap_size].bitset = used;
	Heap[heap_size].cnt = cnt;

	heap_elem elem = Heap[heap_size];
	int next = heap_size >> 1, now = heap_size;

	while (next && Heap[next].cost > elem.cost)
		Heap[now] = Heap[next],
		now = next,
		next >>= 1;
	
	Heap[now] = elem;
}

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

	unsigned int fin_cnt = 0, ans = (1 << 31) * 2 - 1;
	char pos;

	scanf("%d %d %d", &K, &N, &M);
	for (int i = 0, x; i < K; ++i)
		scanf("%d", &x),
		__K[fin_cnt++] = x,
		mode[x] = 1;

	fin_cnt = (1 << fin_cnt) - 1;

	for (int i = 0, A, B, C, D; i < M; ++i){
		scanf("%d %d %d %d", &A, &B, &C, &D);
		node *New1 = new node, *New2 = new node;
		if (D > K) D = K;

		New1->next = A, New1->link = G[B], New1->cost = C, New1->cnt = D;
		New2->next = B, New2->link = G[A], New2->cost = C, New2->cnt = D;
		G[B] = New1;
		G[A] = New2;
	}
	pos = nth_k(1);
	insert(1, 0, pos >= 0 ? 1 << pos : 0, 0);
	if (pos >= 0) insert(1, 0, 0, 0);

	for (int i = 1; i < N; ++i) __dist[i] = ans;
	
	while (heap_size){
		int node = Heap[1].node,
			cost = Heap[1].cost,
			bitset = Heap[1].bitset,
			cnt = Heap[1].cnt;
		pop();
		if ((__bitset[node] == bitset && __dist[node] < cost) || cost >= ans) continue;

		if (bitset == fin_cnt && ans > cost) 
			ans = cost;

		__bitset[node] = bitset, __dist[node] = cost;

		foreach(G[node]){
				if (mode[it->next]) pos = nth_k(it->next);
				else pos = -1;

				if ((pos >= 0 && it->cnt < cnt) || cost + it->cost * (cnt + 1) > ans) continue;

				if (pos >= 0 && ((1 << pos | bitset)) != bitset) insert(it->next, cost + it->cost * (cnt + 1), (1 << pos) | bitset, cnt + 1);
				insert(it->next, cost + it->cost * (cnt + 1), bitset, cnt);
			}
	}

	printf("%d", ans);
	return 0;
}