Cod sursa(job #2176320)

Utilizator flibiaVisanu Cristian flibia Data 16 martie 2018 22:37:42
Problema Ubuntzei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.82 kb
#pragma GCC optimize("03")
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair <int, int>
#define INF 2000000000

using namespace std;

ifstream in("ubuntzei.in");
ofstream out("ubuntzei.out");

int n, m, x, y, c, pw, C[20], dp[2010], D[20][2010], bst[16][1 << 17], lim;
vector <pii> v[2010];
set <pii> h;
vector <int> masks[20];

void Dij(int id){
	h.clear();
	for(int i = 1; i <= n; i++)
		dp[i] = INF;
	dp[C[id]] = 0;
	h.insert({0, C[id]});
	while(!h.empty()){
		pii dad = *h.begin();
		h.erase(h.begin());
		for(auto son : v[dad.se]){
			if(dad.fi + son.fi < dp[son.se]){
				if(dp[son.se] != INF){
					h.erase(h.find({dp[son.se], son.se}));
				}
				dp[son.se] = dad.fi + son.fi;
				h.insert({dp[son.se], son.se});
			}
		}
	}
	for(int i = 1; i <= n; i++)
		D[id][i] = dp[i];
}

void solve(int lvl, int id){
	id--;
	for(auto mask : masks[lvl]){
		if((mask & (1 << id)) == 0)
			continue;
		int msk = (mask ^ (1 << id));
		if(msk == 0){
			bst[id + 1][mask] = D[id + 1][1];
			continue;
		}
		for(int bit = 0; bit < pw; ++bit){
			if(msk & (1 << bit)){
				bst[id + 1][mask] = min(bst[id + 1][mask], bst[bit + 1][msk] + D[id + 1][C[bit + 1]]);
			}
		}
	}
}

int main(){
	in >> n >> m;
	in >> pw;
	for(int i = 1; i <= pw; i++)
		in >> C[i];
	while(m--){
		in >> x >> y >> c;
		v[x].push_back({c, y});
		v[y].push_back({c, x});
	}
	for(int i = 1; i <= pw; i++)
		Dij(i);
	lim = (1 << pw);
	for(int mask = 1; mask < lim; ++mask)
		masks[__builtin_popcount(mask)].push_back(mask);
	for(int i = 1; i <= pw; i++)
		for(int j = 0; j < lim; j++)
			bst[i][j] = INF;
	for(int i = 1; i <= pw; i++)
		for(int j = 1; j <= pw; j++)
			solve(i, j);
	int mn = INF;
	for(int i = 1; i <= pw; i++)
		mn = min(mn, bst[i][lim - 1] + D[i][n]);
	out << mn;
	return 0;
}