Cod sursa(job #582643)

Utilizator ProtomanAndrei Purice Protoman Data 15 aprilie 2011 16:55:45
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.19 kb
#include <algorithm>
#include <stdio.h>
#include <set>
#include <vector>

#define MAX 2048
#define INF 1000000000
#define pb push_back
#define mp make_pair
#define f first
#define s second

using namespace std;

int n, m, k;
int nv[32];
int cost[32][32];
set <pair <int, int> > setMin;
int dist[MAX];
vector <pair <int, int> > vctDrum[MAX];
int sol[1 << 15][16];

inline void dijkstra(int nod)
{	
	setMin.clear();
	
	dist[nod] = 0;
	setMin.insert(mp(0, nod));
	for (int i = 1; i <= n; i++)
		if (i != nod)
		{
			setMin.insert(mp(INF, i));
			dist[i] = INF;
		}
	
	for (; setMin.size(); )
	{
		int loc = (*setMin.begin()).s;
		
		setMin.erase(setMin.begin());
		
		for (int i = 0; i < vctDrum[loc].size(); i++)
			if (dist[vctDrum[loc][i].f] > dist[loc] + vctDrum[loc][i].s)
			{
				setMin.erase(mp(dist[vctDrum[loc][i].f], vctDrum[loc][i].f));
				
				dist[vctDrum[loc][i].f] = dist[loc] + vctDrum[loc][i].s;
				
				setMin.insert(mp(dist[vctDrum[loc][i].f], vctDrum[loc][i].f));
			}
	}
}

int main()
{
	freopen("ubuntzei.in", "r", stdin);
	freopen("ubuntzei.out", "w", stdout);
	
	scanf("%d %d", &n, &m);
	
	scanf("%d", &k);
	
	for (int i = 0; i < k; i++)
		scanf("%d", &nv[i]);
	nv[k] = n;
	
	for (int i = 1; i <= m; i++)
	{
		int n1, n2, c;
		scanf("%d %d %d\n", &n1, &n2, &c);
		
		vctDrum[n1].pb(mp(n2, c));
		vctDrum[n2].pb(mp(n1, c));
	}
	
	dijkstra(1);
	int err = dist[n];
	for (int conf = 1; conf < (1 << k); conf++)
		for (int i = 0; i < k; i++)
			sol[conf][i] = INF;
	for (int i = 0; i < k; i++)
		sol[1 << i][i] = dist[nv[i]];
	
	for (int i = 0; i <= k; i++)
	{
		dijkstra(nv[i]);
		
		for (int j = 0; j <= k; j++)
			cost[i][j] = dist[nv[j]];
	}
	
	for (int conf = 1; conf < (1 << k); conf++)
		for (int i = 0; i < k; i++)
			if (conf & (1 << i))
				for (int j = 0; j < k; j++)
					if (!(conf & (1 << j)))
						sol[conf | (1 << j)][j] = min(sol[conf | (1 << j)][j], sol[conf][i] + cost[i][j]);
					
	int rez = INF;
	for (int i = 0; i < k; i++)
		rez = min(rez, sol[(1 << k) - 1][i] + cost[i][k]);
	
	if (!k)
		printf("%d\n", err);
	else printf("%d\n", rez);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}