Cod sursa(job #670087)

Utilizator AndreiRSStatescu Andrei Rares AndreiRS Data 28 ianuarie 2012 12:34:01
Problema Ubuntzei Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.42 kb
#include <fstream>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;

ifstream fi ("ubuntzei.in");
ofstream fo ("ubuntzei.out");

const int dim = 2005, dimk = 20, OO = (1<<31)-1;
int N, M, K, Cmin, OK[dimk], DK[dimk][dimk];
int H[dim], D[dim], P[dim];
struct vec { int v, c; };
vector <vec> V[dim];
bitset <dim> viz;

void cit ()
{
	vec v;
	
	fi >> N >> M >> K;
	for (int i = 1; i <= K; i++)
		fi >> OK[i];
	OK[++K] = 1;
	OK[++K] = N;
	sort (OK + 1, OK + K + 1);
	
	for (int i = 1, x, y; i <= M; i++)
	{
		fi >> x >> y >> v.c;
		v.v = y;
		V[x].push_back (v);
		v.v = x;
		V[y].push_back (v);
	}
	
	Cmin = OO;
}

void upheap (int f)
{
	int t = f >> 1;
	while (t != 0 && D[H[t]] > D[H[f]])
	{
		swap (H[t], H[f]);
		swap (P[H[t]], P[H[f]]);
		
		f = t;
		t = f >> 1;
	}
}

void downheap (int t)
{
	int f = t << 1;
	if (f+1 <= H[0] && D[H[f+1]] < D[H[f]]) f++;
	while (f <= H[0] && D[H[f]] < D[H[t]])
	{
		swap (H[f], H[t]);
		swap (P[H[f]], P[H[t]]);
		
		t = f;
		f = t << 1;
		if (f+1 < H[0] && D[H[f+1]] < D[H[f]]) f++;
	}
}

void init ()
{
	for (int i = 0; i <= N; i++)
	{
		D[i] = OO;
		H[i] = P[i] = i;
		viz[i] = 0;
	}	
}

void dijkstra (int ik)
{
	int s = OK[ik], n, v, c, j;

	D[s] = 0;
	H[0] = N;
	upheap (s);
	
	while (H[0] > 0)
	{
		n = H[1];
		viz[n] = 1;
		H[1] = H[H[0]];
		P[H[H[0]]] = 1;
		H[0]--;
		downheap (1);
		
		for (j = 0; j < V[n].size(); j++)
		{
			v = V[n][j].v;
			c = V[n][j].c;
			if (viz[v] == 0)
			{
				if (D[v] > D[n] + c)
					D[v] = D[n] + c;
				upheap (P[v]);
				downheap (P[v]);
			}
		}		
	}

	for (int i = 1, j = 1; i <= N; i++)
		if (i == OK[j])
			DK[ik][j++] = D[i];
}
/*
void warshall ()
{
	int i, j, k;
	for (k = 1; k <= K; k++)
	{
		for (i = 1; i <= K; i++)
			for (j = 1; j <= K; j++)
				if (DK[i][j] > DK[i][k] + DK[k][j])
					DK[i][j] = DK[i][k] + DK[k][j];
	}
}
*/

void back (int n, int k, int ct)
{
	if (ct > Cmin) 
		return;
	if (k == K - 1 && ct + DK[n][K] < Cmin)
	{
		Cmin = ct + DK[n][K];
		return;
	}
	
	for (int i = 2, c; i < K; i++)
	{
		c = DK[n][i];
		if (viz[i] == 0)
		{
			viz[i] = 1;
			back (i, k + 1, ct + c);
			viz[i] = 0;
		}
	}
}

void afi ()
{
	fo << Cmin << '\n';
}

int main ()
{
	cit ();
	for (int i = 1; i <= K; i++)
	{
		init ();
		dijkstra (i);
	}
	init ();
	back (1, 1, 0);
	afi ();
	return 0;
}