Cod sursa(job #1977580)

Utilizator greenadexIulia Harasim greenadex Data 5 mai 2017 15:53:16
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.97 kb
#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define pii pair<int, int>
#define mp make_pair
 
using namespace std;
 
const string name = "ubuntzei",
             in_file = name + ".in",
             out_file = name + ".out";
 
ifstream fin(in_file);
ofstream fout(out_file);
 
const int NMAX = 2e3 + 1, MMAX = 1e4 + 1, KMAX = 16, INF = (1LL << 31) - 1;

struct Edge {
	int node;
	int cost;

	Edge(int node, int cost) {
		this->node = node;
		this->cost = cost;
	}
};

int n, m, k;
int cities[KMAX];
int dist_from_start[NMAX];
int dist_from_finish[NMAX];
int dist[KMAX][NMAX];
int dp[(1 << KMAX)][KMAX];

bitset<NMAX> visited;
vector<Edge> graph[NMAX];
priority_queue<pii, vector<pii>, greater<pii>> pqueue;

void clear_queue() {
	while (!pqueue.empty()) {
		pqueue.pop();
	}
}

void dijkstra(int source, int dist[]) {
	clear_queue();
	
	for (int i = 1; i <= n; i++) {
		dist[i] = (i == source ? 0 : INF);
	}

	visited = 0;
	pqueue.emplace(dist[source], source);

	while (!pqueue.empty()) {
		int node = pqueue.top().s;
		pqueue.pop();

		if (visited[node]) {
			continue;
		}
		visited[node] = 1;

		for (Edge adj : graph[node]) {
			if (adj.cost + dist[node] < dist[adj.node]) {
				dist[adj.node] = adj.cost + dist[node];
				pqueue.emplace(dist[adj.node], adj.node);
			}
		}
	}
}

bool power_of_two(int nr) {
	return (nr & (nr - 1)) == 0;
}

int log_base_2(int nr) {
	int cnt = 1;
	while (nr > 1) {
		nr /= 2;
		cnt++;
	}
	return cnt;
}

int main() {
	fin >> n >> m >> k;
	for (int i = 1; i <= k; i++) {
		fin >> cities[i];
	}

	for (int x, y, c, i = 1; i <= m; i++) {
		fin >> x >> y >> c;
		graph[x].emplace_back(y, c);
		graph[y].emplace_back(x, c);
	}

	dijkstra(1, dist_from_start);
	dijkstra(n, dist_from_finish);

	for (int i = 1; i <= k; i++) {
		dijkstra(cities[i], dist[i]);
	}

	if (!k) {
		fout << dist_from_start[n];
		return 0;
	}

	int max_mask = (1 << k) - 1;
	for (int mask = 1; mask <= max_mask; mask++) {
		for (int i = 1; i <= k; i++) {
			dp[mask][i] = INF;
		}
	}
	
	for (int mask = 1; mask <= max_mask; mask++) {
		if (!power_of_two(mask)) {
			for (int first_bit = 0; first_bit < k; first_bit++) {
				if (mask & (1 << first_bit)) {
					for (int second_bit = 0; second_bit < k; second_bit++) {
						if (first_bit == second_bit) {
							continue;
						}

						if (mask & (1 << second_bit)) {
							int second_city = cities[second_bit + 1];
							int additional = 0;
							
							if (mask == max_mask) {
								additional = dist_from_finish[second_city];
							}

							dp[mask][first_bit + 1] = min(dp[mask][first_bit + 1],
								dp[mask - (1 << first_bit)][second_bit + 1] + 
								dist[first_bit + 1][second_city] + additional);
						}
					}
				}
			}
		} else {
			int vaca = log_base_2(mask);
			dp[mask][vaca] = dist_from_start[cities[vaca]];
			if (mask == max_mask) {
				dp[mask][vaca] += dist_from_finish[cities[vaca]];
			}
		}
	} 
	
	int sol = INF;
	for (int i = 1; i <= k; i++) {
		sol = min(sol, dp[max_mask][i]);
	}
	cout << sol;
	return 0;
}