Cod sursa(job #2982681)

Utilizator Radu_TudorRadu Tudor Radu_Tudor Data 20 februarie 2023 18:36:23
Problema Ubuntzei Scor 35
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.43 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <limits.h>

#define INF 0x3F3F3F3F

using namespace std;

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

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];

// dijkstra
long long DIST[N_MAX];
bool IN_Q[N_MAX];
struct compare {

	bool operator () (int x, int y) {

		return (DIST[x] > DIST[y]);
	}
};
priority_queue<int, vector<int>, compare> Q;

// backtracking
int X[N_MAX];

// result
long long min_dist = LLONG_MAX;

void read() {

	fin >> N >> M;

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

	int x, y, cost;
	for (int i = 1; i <= M; i++) {

		fin >> x >> y >> cost;

		edges[x].push_back(make_pair(y, cost));
		edges[y].push_back(make_pair(x, cost));
	}
}

void setup() {

	for (int i = 1; i <= N; i++)
		DIST[i] = INF;
}

void dijkstra(int start_node) {

	setup();
	DIST[start_node] = 0;

	Q.push(start_node);
	IN_Q[start_node] = true;

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

		int current_node = Q.top();
		IN_Q[current_node] = false;

		Q.pop();

		for (size_t i = 0; i < edges[current_node].size(); i++) {

			int neighbour_node = edges[current_node][i].first;
			int cost = edges[current_node][i].second;

			if (DIST[neighbour_node] > DIST[current_node] + cost) {

				DIST[neighbour_node] = DIST[current_node] + cost;

				if (IN_Q[neighbour_node] == false)
					Q.push(neighbour_node),
					IN_Q[neighbour_node] = true;
			}
		}
	}
}

bool valid(int k) {
		
	for (int i = 1; i < k; i++)
		if (X[i] == X[k])
			return false;

	return true;
}

bool solution(int k) {

	return (k == K);
}

void update() {

	dijkstra(1);

	long long current_dist = 0;
	for (int i = 1; i <= K; i++) {

		current_dist += DIST[X[i]];
		dijkstra(X[i]);
	}

	current_dist += DIST[N];

	if (current_dist < min_dist)
		min_dist = current_dist;
}

void backtracking(int k) {

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

		X[k] = cities[i];

		if (valid(k)) {

			if (solution(k))
				update();
			else
				backtracking(k + 1);
		}
	}
}

void solve() {

	if (K == 0)
		dijkstra(1),
		fout << DIST[N];
	else
		backtracking(1),
		fout << min_dist;
}

int main() {

	read();
	solve();

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

	return 0;
}