Cod sursa(job #1110167)

Utilizator SmarandaMaria Pandele Smaranda Data 17 februarie 2014 21:09:00
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.85 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream fin ("ubuntzei.in");
ofstream fout ("ubuntzei.out");

struct Edge {
	long x, c;
};

const long K = 20, N = 2001, S = (1 << 16), inf = 2000000000;
long n, m, k;
long must [K], h [N], l[N] [N], poz [N], z, dp [S][K], final;
vector <Edge> v [N];

void read () {
	long i, x, y, c;
	Edge temp;
	fin >> n >> m >> k;
	for (i = 1; i <= k; i ++)
		fin >> must [i];
	must [0] = 1;
	for (i = 1; i <= m; i ++) {
		fin >> x >> y >> c;
		temp.x = y;
		temp.c = c;
		v [x].push_back (temp);
		temp.x = x;
		v [y].push_back (temp);
	}
}

void init () {
	long i;
	h [0] = 0;
	for (i = 1; i <= n; i ++) {
		l [z][i] = inf;
		poz [i] = -1;
	}
}

void  up (long x) {
	long father, aux;
	while (x > 1) {
		father = x >> 1;
		if (l [z][h [father]] > l [z][h [x]]) {
			poz [h [father]] = x;
			poz [h [x]] = father;
			aux = h [father];
			h [father] = h [x];
			h [x]= aux;
			x= father;
		}
		else break;
	}
}

void down (long x) {
	long left, right, son, aux;
	while (1) {
		left = x << 1;
		if (left <= h [0]) {
			son = left;
			right = left + 1;
			if (right <= h [0] && l [z][h[right]]< l [z][h [left]])
				son = right;
			if  (l [z][h [son]] < l [z][h [x]]) {
				poz [h [son]] = x;
				poz [h [x]] = son;
				aux = h [son];
				h [son] = h [x];
				h [x] = aux;
				x = son;
			}
			else break;
		}
		else break;
	}
}

void insert (long x) {
	h [++ h [0]] = x;
	poz [x] = h [0];
	up (poz [x]);
}

void pop () {
	h [1] = h [h [0]];
	poz [h [1]] = 1;
	h [0] --;
	down (1);
}

void dijkstra () {
	long a, d;
	Edge temp;
	vector <Edge> :: iterator it;
	init ();
	h [++ h [0]] = z;
	l [z][z]= 0;
	while (h [0]) {
		a = h [1];
		pop ();
		for (it = v [a].begin (); it != v [a].end (); it ++) {
			temp = *it;
			d = temp.c + l [z][a];
			if (d < l [z][temp.x]) {
				l [z][temp.x] = d;
				if (poz [temp.x] != -1)
					up (poz [temp.x]);
				else
					insert (temp.x);
			}
		}
	}
}

long ciclu (long config,  long x) {
	long i, e;
	if (dp [config][x] == -1)  {
		dp [config][x] = inf;
		for (i = 0; i <= k; i ++)
			if (must [i] !=  must [x]){
				if (config & (1 << i))
					if (!(i == 0 && config != (1 << x) + 1)) {
						e = ciclu (config ^ (1 << x), i) + l [must [i]][must [x]];
						if (e < dp [config][x])
							dp [config][x] = e;
					}
			}
	}
	return dp [config][x];
}

void solve () {
	long i, min1, g, j;
	z = 1;
	for (i = 0; i <= k; i ++) {
		z = must [i];
		dijkstra ();
	}
	final = (1 << (k + 1)) - 1;
	min1 = inf;
	for (i = 0; i <= final; i ++)
		for (j = 0; j <= k; j ++)
			dp [i][j] = -1;
		dp [1][0] = 0;
	for (i = 0; i <= k; i ++)  {
		g = ciclu (final,  i) + l [must [i]][n];
		if (min1 > g)
			min1 = g;
	}
	fout << min1 << "\n";
}

int main () {
	read ();
	solve ();
	return 0;
}