Cod sursa(job #2977708)

Utilizator TudosieRazvanTudosie Marius-Razvan TudosieRazvan Data 12 februarie 2023 12:08:27
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.45 kb
#include <cstdio>
#include <climits>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <bitset>
#include <map>
#include <cstring>
#include <algorithm>

#define NMAX 2003


using namespace std;


FILE* fin, * fout;

int n, m, k;
int v[NMAX];
int dist[17][NMAX];
int dp[17][1<<17];
struct muchie {
	int vecin, cost;
	bool operator()(const muchie& a, const muchie& b) const {
		return a.cost > b.cost;
	}
};
vector<muchie>graf[NMAX];
bool viz[NMAX];

void djikstra(int poz)
{
	for (int i = 0; i <= n; i++)
	{
		viz[i] = false;
		dist[poz][i] = INT_MAX;
	}

	priority_queue<muchie, vector<muchie>, muchie>q;
	q.push({ v[poz],0 });
	dist[poz][v[poz]] = 0;
	while (!q.empty())
	{
		int nPrec = q.top().vecin;
		int cPrec = q.top().cost;
		if (viz[nPrec])
		{
			q.pop();
			continue;
		}
		viz[nPrec] = true;
		for (int i = 0; i < graf[nPrec].size(); i++)
		{
			int nd = graf[nPrec][i].vecin;
			int costMuchie = graf[nPrec][i].cost;
			if (!viz[nd] && dist[poz][nd] > cPrec + costMuchie)
			{
				dist[poz][nd] = cPrec + costMuchie;
				q.push({ nd,dist[poz][nd] });
			}
		}
	}
}

int main()
{
	fin = fopen("ubuntzei.in", "r");
	fout = fopen("ubuntzei.out", "w");

	fscanf(fin, "%d %d %d", &n, &m, &k);
	for (int i = 1; i <= k; i++)
	{
		fscanf(fin, "%d", &v[i]);
	}
	for (int i = 1; i <= m; i++)
	{
		int x, y, c;
		fscanf(fin, "%d %d %d", &x, &y, &c);
		graf[x].push_back({ y,c });
		graf[y].push_back({ x,c });
	}
	v[++k] = 1;
	//fac distantele minime
	for (int i = 1; i <= k; i++)
	{
		djikstra(i);
	}
	if (k == 1)
	{
		//nu am elem pe unde sa trec
		fprintf(fout, "%d", dist[1][n]);
		return 0;
	}
	k--;
	//acum fac dinamica
	for (int i = 1; i <= k; i++)
	{

		for (int stare = 1; stare <= (1 << k) - 1; stare++)
		{
			dp[i][stare] = INT_MAX;

		}
		dp[i][1 << (i - 1)] = dist[i][1];

	}
	for (int stare = 1; stare < (1 << k); stare++)
	{
		for (int i = 1; i <= k; i++)
		{
			if (dp[i][stare] != INT_MAX)
			{
				for (int j = 1; j <= k; j++)
				{
					if (((stare >> (j - 1)) & 1) == false)
					{
						//pot ajunge aici
						int nouaStare = stare + (1 << (j - 1));
						dp[j][nouaStare] = min(dp[j][nouaStare], dp[i][stare] + dist[j][v[i]]);
					}
				}
			}
		}
	}
	int minim = INT_MAX;
	for (int i = 1; i <= k; i++)
	{
		minim = min(minim, dp[i][(1 << k) - 1] + dist[i][n]);
	}
	fprintf(fout, "%d", minim);
	return 0;
}