Cod sursa(job #698556)

Utilizator mottyMatei-Dan Epure motty Data 29 februarie 2012 14:49:56
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.13 kb
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <set>

using namespace std;

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

const int K = 18;
const int N = 2002;

int n, k;
int obj[K];
int d[K][K];

vector <int> g[N];
vector <int> c[N];

void Read()
{
	int m;
	in >> n >> m >> k;

	for (int i = 1; i <= k; ++i)
		in >> obj[i];
	obj[0] = 1;
	obj[k+1] = n;

	while (m--)
	{
		int a, b, cost;
		in >> a >> b >> cost;

		g[a].push_back(b), c[a].push_back(cost);
		g[b].push_back(a), c[b].push_back(cost);
	}
}

set < pair<int,int> > s; // cost, nod
int cost[N];

void Check(int cst, int node)
{
	for (int i = 0; i < g[node].size(); ++i) {
		int next = g[node][i];

		if (cst + c[node][i] < cost[next]) {
			cost[next] = cst + c[node][i];
			s.insert(make_pair(cost[next], next));
		}
	}
}

void Dijkstra(int node)
{
	memset(cost, 0x3f3f3f3f, sizeof(cost));
	cost[node] = 0;
	s.insert(make_pair(0, node));

	for (int i = 1; i <= n; ++i) {
		pair <int,int> curState = *s.begin();
		int cst = curState.first;
		int node = curState.second;

		s.erase(s.begin());
		Check(cst, node);
	}
}

void UpdateDistances(int node)
{
	for (int i = 1; i <= k+1; ++i)
		d[node][i] = cost[obj[i]];
}

int a[K][1 << K];

inline int bitter(int x)
{
	return 1 << (x-1);
}

int HamiltonCheck()
{
	memset(a, 0x3f3f3f3f, sizeof(a));

	for (int i = 1; i <= k; ++i)
		a[i][1 << (i-1)] = d[0][i];

	for (int conf = 0; conf < (1<<k) - 1; ++conf)
		for (int i = 1; i <= k; ++i)
			if (a[i][conf] < 0x3f3f3f3f)
				for (int j = i; j <= k; ++j)
					if (bitter(j)^conf && a[j][conf + bitter(j)] > a[i][conf] + d[i][j])
						a[j][conf + bitter(j)] = a[i][conf] + d[i][j];

	int best = 0x3f3f3f3f;
	for (int i = 1; i <= k; ++i)
		if (a[i][(1<<k) - 1] + d[i][n] < best)
			best = a[i][(1<<k) - 1] + d[i][k+1];

	return best;
}

int main()
{
	Read();

	for (int i = 0; i <= k; ++i) {
		Dijkstra(obj[i]); // Merge
		UpdateDistances(i);
	}

	if (k == 0)
	{
		out << d[0][k+1] << "\n";
		return 0;
	}

	out << HamiltonCheck() << "\n";

	return 0;
}