Cod sursa(job #2985615)

Utilizator Radu_TudorRadu Tudor Radu_Tudor Data 26 februarie 2023 18:34:33
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.26 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <math.h>
#include <limits.h>

#define INF 0x3F3F3F3F

using namespace std;

const string FILE_NAME = "ubuntzei";
const int N_MAX = 2e3 + 1;
const int K_MAX = 15 + 1;

ifstream fin(FILE_NAME + ".in");
ofstream fout(FILE_NAME + ".out");

int N, M;
int K;
int cities[K_MAX];

vector<pair<int, int>> edges[N_MAX];

// DP
int DP[2 << K_MAX][K_MAX];

// dijkstra
int DIST[K_MAX][N_MAX];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > Q;

// result
int minimum_distance = INF;

void read() {

	fin >> N >> M;

	fin >> K;
	for (int i = 0; i < K; i++)
		fin >> cities[i];

	int from, to, cost;
	for (int i = 1; i <= M; i++) {

		fin >> from >> to >> cost;

		edges[from].push_back(make_pair(to, cost));
		edges[to].push_back(make_pair(from, cost));
	}
}

void dijkstra(int start_node, int dist[]) {

	for (int i = 1; i <= N; i++)
		dist[i] = INF;
	dist[start_node] = 0;

	Q.push(make_pair(0, start_node));

	while (Q.empty() == false) {

		int node = Q.top().second;
		Q.pop();

		for (auto edge : edges[node]) {

			int neighbour = edge.first;
			int cost = edge.second;

			if (dist[neighbour] > dist[node] + cost) {

				dist[neighbour] = dist[node] + cost;
				Q.push(make_pair(dist[neighbour], neighbour));
			}
		}
	}
}

void solve() {

	dijkstra(1, DIST[K]);
	for (int k = 0; k < K; k++)
		dijkstra(cities[k], DIST[k]);

	for (int k = 0; k < K; k++)
		DP[(1 << k)][k] = DIST[K][cities[k]];

	for (int mask = 1; mask < (1 << K); mask++) {

		if ((mask & (mask - 1)) == 0)
			continue;

		for (int j = 0; j < K; j++)
			DP[mask][j] = INT_MAX;

		for (int j = 0; j < K; j++)
			if (mask >> j & 1)
				for (int i = 0; i < K; i++)
					if (mask >> i & 1)
						if (i != j)
							DP[mask][j] = min(DP[mask][j], DP[mask - (1 << j)][i] + DIST[j][cities[i]]);
	}

	int mask = (1 << K) - 1;

	for (int j = 0; j < K; j++)
		minimum_distance = min(minimum_distance, DP[mask][j] + DIST[j][N]);

	if (K == 0)
		minimum_distance = DIST[0][N];
}

void display() {

	fout << minimum_distance;
}

int main() {

	read();
	solve();
	display();

	fin.close();
	fout.close();

	return 0;
}