Cod sursa(job #1301155)

Utilizator vladrochianVlad Rochian vladrochian Data 25 decembrie 2014 17:42:01
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.9 kb
#include <fstream>
#include <queue>
#include <cstring>
using namespace std;

const int kMaxN = 2005, kMaxK = 17, kMaxConf = 65540, kInf = 0x3f3f3f3f;

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

int N, M, K, dist[kMaxN], friends[kMaxK], frdist[kMaxK][kMaxK], cdist[kMaxConf][kMaxK];
vector<pair<int, int>> G[kMaxN];
struct HeapMember {
	int node, cost;
	HeapMember(int n, int c) {
		node = n;
		cost = c;
	}
	bool operator<(const HeapMember &other) const {
		return cost > other.cost;
	}
};
priority_queue<HeapMember> Q;

void Read() {
	fin >> N >> M >> K;
	for (int i = 0; i < K; ++i)
		fin >> friends[i];
	friends[K++] = N;
	while (M--) {
		int x, y, c;
		fin >> x >> y >> c;
		G[x].push_back(make_pair(y, c));
		G[y].push_back(make_pair(x, c));
	}
}

void Dijkstra(int source) {
	memset(dist, kInf, sizeof dist);
	dist[source] = 0;
	Q.push(HeapMember(source, 0));
	while (!Q.empty()) {
		int node = Q.top().node, cost = Q.top().cost;
		Q.pop();
		if (cost != dist[node])
			continue;
		for (auto it : G[node]) {
			int new_dist = dist[node] + it.second;
			if (new_dist < dist[it.first]) {
				dist[it.first] = new_dist;
				Q.push(HeapMember(it.first, new_dist));
			}
		}
	}
}

int main() {
	Read();
	Dijkstra(1);
	if (K == 1) {
		fout << dist[N] << "\n";
		return 0;
	}
	memset(cdist, kInf, sizeof cdist);
	for (int i = 0; i < K; ++i)
		cdist[1 << i][i] = dist[friends[i]];
	for (int i = 0; i < K; ++i) {
		Dijkstra(friends[i]);
		for (int j = 0; j < K; ++j)
			frdist[i][j] = dist[friends[j]];
	}
	int lim = 1 << K;
	for (int i = 3; i < lim; ++i)
		for (int j = 0; j < K; ++j)
			if (i & (1 << j) && cdist[i][j] == kInf) {
				int prev = i ^ (1 << j);
				for (int k = 0; k < K; ++k)
					if (prev & (1 << k))
						cdist[i][j] = min(cdist[i][j], cdist[prev][k] + frdist[k][j]);
			}
	fout << cdist[lim - 1][K - 1] << "\n";
	return 0;
}