Cod sursa(job #615781)

Utilizator Catah15Catalin Haidau Catah15 Data 10 octombrie 2011 20:56:12
Problema Ubuntzei Scor 95
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.8 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

#define maxN 2005
#define maxK 18
#define maxConf (1 << 18)
#define inf (1 << 30)
#define PB push_back
#define MKP make_pair


vector < pair <int, int> > lista[maxN];
int c[maxK], cost[maxN], cost2[maxK][maxK];
int H[maxN], poz[maxN];
bool cont[maxN];
int dimH;
int sol[maxConf][maxK];


void pop (int nod)
{
	int nodmin = nod, st = nod * 2, dr = nod * 2 + 1;
	
	if (st <= dimH && cost[H[nodmin]] > cost[H[st]]) nodmin = st;
	if (dr <= dimH && cost[H[nodmin]] > cost[H[dr]]) nodmin = dr;
	
	if (nodmin == nod) return;
	
	swap (H[nod], H[nodmin]);
	swap (poz[H[nod]], poz[H[nodmin]]);
	
	pop (nodmin);
}


void push (int nod)
{
	if (nod == 1) return;
	if (cost[H[nod]] >= cost[H[nod / 2]]) return;
	
	swap (H[nod], H[nod / 2]);
	swap (poz[H[nod]], poz[H[nod / 2]]);
	
	push (nod / 2);
}


int main()
{
	freopen ("ubuntzei.in", "r", stdin);
	freopen ("ubuntzei.out", "w", stdout);
	
	int N, M, K;
	
	scanf ("%d %d %d", &N, &M, &K);
	
	c[0] = 1;
	
	for (int i = 1; i <= K; ++ i) scanf ("%d", &c[i]);
	
	c[++ K] = N;
	
	while (M --)
	{
		int x, y, z;
		
		scanf ("%d %d %d", &x, &y, &z);
		
		lista[x]. PB ( MKP (y, z) );
		lista[y]. PB ( MKP (x, z) );
	}
	
	
	for (int n = 0; n < K; ++ n)
	{
		int NOD = c[n];
		
		H[1] = NOD;
		poz[1] = 1;
		cost[NOD] = 0;
		
		dimH = 1;
		
		for (int i = 1; i <= N; ++ i)
		{
			if (i == NOD) continue;
			
			H[++ dimH] = i;
			cost[i] = inf;
			
			poz[i] = dimH;
		}
		
		for (int i = 1; i <= N; ++ i)
		{
			int nod = H[1];
			
			cont[nod] = true;
			
			swap (H[1], H[dimH]);
			swap (poz[nod], poz[H[dimH]]);
			-- dimH;
			
			pop (1);
			
			for (unsigned int t = 0; t < lista[nod].size(); ++ t)
			{
				int node = lista[nod][t].first;
				int costt = lista[nod][t].second;
				
				if (cont[node]) continue;
				
				if (cost[node] > cost[nod] + costt)
				{
					cost[node] = cost[nod] + costt;
					
					int pos = poz[node];
					
					if (cost[H[pos / 2]] < cost[H[pos]]) pop (pos);
					else push (pos);
				}
			}
		}
		
		memset (cont, false, sizeof (cont));
		
		for (int i = 0; i <= K; ++ i)
			cost2[n][i] = cost[c[i]];
	}
	
	
	for (int i = 0; i < (1 << (K + 1)); ++ i)
		for (int j = 0; j <= K; ++ j) sol[i][j] = inf;
	
	sol[1][0] = 0;
	
	++ K;

	for (int i = 0; i < (1 << K); ++ i)
		for (int j = 1; j < K; ++ j)
		{
			if (! (i & (1 << j))) continue;
			
			for (int bit = 0; bit < K; ++ bit)
			{
				if (bit == j) continue;
				if (! (i & (1 << bit))) continue;
				if (cost2[bit][j] == inf) continue;
				
				sol[i][j] = min (sol[i][j], sol[i - (1 << j)][bit] + cost2[bit][j]);
			}
		}
	
	
	printf ("%d", sol[(1 << K) - 1][K - 1]);
	
	return 0;
}