Cod sursa(job #2630843)

Utilizator CosminMorarMorar Cosmin Andrei CosminMorar Data 27 iunie 2020 14:39:29
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.41 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");
int n, m, k, need[15], d_min[2010][2010], d_part[33000][15];
vector<pair<int, int> > edges[2010];

void dijkstra(int);
bool e_putere_a_lui_2(int);

int main() {
	fin >> n >> m >> k;
	for (int i = 0; i < k; i++)
		fin >> need[i];
	for (int i = 1; i <= m; i++) {
		int a, b, cost;
		fin >> a >> b >> cost;
		edges[a].emplace_back(b, cost);
		edges[b].emplace_back(a, cost);
	}

	/// calculam distantele dintre noduri
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			d_min[i][j] = 2e9;

	dijkstra(1);
	dijkstra(n);
	for (int i = 0; i < k; i++)
		dijkstra(need[i]);

	/// pentru fiecare set de noduri in care trebuie sa mergem
	/// calculam distanta minima pe care o parcurgem ca sa
	/// trecem prin toate acele noduri si sa ajungem in fiecare dintre ele
	int set_complet = (1 << k) - 1;
	for (int i = 1; i <= set_complet; i++)
		for (int j = 0; j < k; j++)
			d_part[i][j] = 1e9;

	int last_node = -1;
	for (int set_act = 1; set_act <= set_complet; set_act++)
		if (e_putere_a_lui_2(set_act)) {
			last_node++;
			d_part[set_act][last_node] = d_min[1][need[last_node]];
		} else
			for (int nod_exclus = 0; (1 << nod_exclus) <= set_act; nod_exclus++)
				if ((1 << nod_exclus) & set_act)
					for (int end_nod_ant = 0; end_nod_ant <= last_node; end_nod_ant++)
						if ((1 << end_nod_ant) & set_act)
							if (nod_exclus != end_nod_ant)
								d_part[set_act][nod_exclus] = min(d_part[set_act][nod_exclus], d_part[set_act - (1 << nod_exclus)][end_nod_ant] + d_min[need[nod_exclus]][need[end_nod_ant]]);

	int d_tot = 1e9;
	for (int i = 0; i <= last_node; i++)
		d_tot = min(d_tot, d_part[set_complet][i] + d_min[n][need[i]]);
	if (k == 0)
		d_tot = d_min[1][n];
	fout << d_tot << '\n';
    return 0;
}

bool e_putere_a_lui_2(int x) {
	return ((x ^ (x - 1)) & x) == x;
}

void dijkstra(int start) {
	priority_queue<pair<int, int> > pq;

	pq.push(make_pair(0, start));
	d_min[start][start] = 0;

	while (!pq.empty()) {
		int d_act = -pq.top().first;
		int nod_act = pq.top().second;
		pq.pop();

		if (d_min[start][nod_act] < d_act)
			continue;

		for (pair<int, int> way : edges[nod_act])
			if (d_min[start][way.first] > d_act + way.second) {
				d_min[start][way.first] = d_act + way.second;
				pq.push(make_pair(-d_min[start][way.first], way.first));
			}
	}
}