Cod sursa(job #1618128)

Utilizator TataruTataru Mihai Tataru Data 27 februarie 2016 18:22:27
Problema Ubuntzei Scor 75
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.31 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>
#include <set>
#include <cassert>
#include <memory.h>
#include <algorithm>

using namespace std;

const char inFile[] = "ubuntzei.in";
const char outFile[] = "ubuntzei.out";

const int MAXN = 10005;
const int MAXK = 17;
const int INF = 0x3f3f3f3f;

vector < pair <int, int> > adj[MAXN], adjK[MAXK];
int dist[MAXK][1 << MAXK];
priority_queue < pair <int, int> > q;

vector <int> dijkstra(int src, int nodeCount, vector < pair <int, int> >* adj) {
	vector <int> d(nodeCount, INF);
	vector < pair <int, int> >::iterator it;

	d[src] = 0;
	for (q.push(make_pair(-d[src], src)); !q.empty(); ) {
		int u = q.top().second;
		int dq = -q.top().first;
		q.pop();
		if (d[u] < dq)  continue ;
		for (it = adj[u].begin(); it != adj[u].end(); ++ it) {
			int v = (*it).first;
			int cost = (*it).second;
			if (d[v] > d[u] + cost) {
				d[v] = d[u] + cost;
				q.push(make_pair(-d[v], v));
			}
		}
	}
	return d;
}

priority_queue < pair <int, pair <int, int> > > qk;

int dijkstraK(int src, int snk, int nk, vector < pair <int, int> >* adjK) {
	memset(dist, INF, sizeof dist);
	dist[src][1 << src] = 0;
	for (qk.push(make_pair(0, make_pair(src, 1 << src))); !qk.empty(); ) {
		int u = qk.top().second.first;
		int s = qk.top().second.second;
		int d = -qk.top().first;
		qk.pop();
		if (dist[u][s] < d)  continue;

		for (vector < pair <int, int> >::iterator it = adjK[u].begin(); it != adjK[u].end(); ++ it) {
			int v = (*it).first;
			int cost = (*it).second;

			if (!(s & (1 << v))) {
				int t = s | (1 << v);
				if (dist[v][t] > dist[u][s] + cost) {
					dist[v][t] = dist[u][s] + cost;
					qk.push(make_pair(-dist[v][t], make_pair(v, t)));
				}
			}
		}
	}
	return dist[snk][(1 << nk) - 1];
}

int main() {
	int nodeCount, edgeCount, subsetCount, u, v, cost;

	ifstream in(inFile);
	in >> nodeCount >> edgeCount >> subsetCount;
	int src  = 0;
	int snk = nodeCount - 1;
	vector <int> subset(subsetCount), idxSubset(nodeCount);  bitset <MAXN> inSubset;

	for (int i = 0; i < subsetCount; ++ i) {
		in >> u; -- u;
		assert(0 < u && u < nodeCount - 1);
		idxSubset[ subset[i] = u ] = i;
		inSubset[u] = true;
	}
	subset.push_back(src), idxSubset[src] = (int) subset.size() - 1, inSubset[src] = true;
	subset.push_back(snk), idxSubset[snk] = (int) subset.size() - 1, inSubset[snk] = true;
	for (int i = 0; i < edgeCount; ++ i) {
		in >> u >> v >> cost;
		-- u, -- v;
		assert(0 <= u && u < nodeCount);
		assert(0 <= v && v < nodeCount);
		adj[u].push_back(make_pair(v, cost));
		adj[v].push_back(make_pair(u, cost));
	}
	in.close();

	vector <int> d;

	d = dijkstra(src, nodeCount, adj);
	for (size_t i = 0; i < d.size(); ++ i) if (inSubset[i]) {
		assert(d[i] < INF);
		if ((int) i != src)
			adjK[ idxSubset[src] ].push_back(make_pair(idxSubset[i], d[i]));
	}

	if (subsetCount > 0) {
		for (size_t i = 0; i < subset.size(); ++ i) if (subset[i] != src && subset[i] != snk) {
			d = dijkstra(subset[i], nodeCount, adj);
			for (size_t j = 0; j < d.size(); ++ j) if (inSubset[j]) {
				assert(d[j] < INF);
				if (subset[i] != (int) j)
					adjK[i].push_back(make_pair(idxSubset[j], d[j]));
			}
		}

		int answer = dijkstraK(idxSubset[src], idxSubset[snk], subset.size(), adjK);
		assert(answer < INF);
		ofstream(outFile) << answer << "\n";
	}
	else
		ofstream(outFile) << d[nodeCount - 1] << "\n";
}