Cod sursa(job #581586)

Utilizator savimSerban Andrei Stan savim Data 14 aprilie 2011 13:02:11
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.59 kb
#include <stdio.h>
#include <string.h>
#include <set>
#include <vector>
#include <algorithm>

using namespace std;

#define inf 2000000000

#define MAX_N 2010
#define MAX_K 17
#define MAX_P2 131072

#define mp make_pair

int n, m, k;
int d[MAX_N];

int c[MAX_K];
int road[MAX_K][MAX_K]; //lungimea drumurilor minime intre oricare doua puncte de interes

int sol[MAX_K][MAX_P2];

vector <int> G[MAX_N], cost[MAX_N];

typedef set <pair <int, int> > MYSET;
MYSET s;

void get_dist() {
	for (int i = 0; i < k; i++) {
		for (int j = 1; j <= n; j++)
			d[j] = inf;
		d[c[i]] = 0;
		
		s.clear();
		s.insert(mp(0, c[i]));
		
		int count = 1; //numarul de elemente din set
		
		while (count) {
			MYSET::iterator it = s.begin();
			int vertex = it->second;
			
			s.erase(it);
			count--;
			
			int len = G[vertex].size();
			for (int j = 0; j < len; j++) {				
				int son = G[vertex][j];
				
				if (d[son] == inf) {
					d[son] = d[vertex] + cost[vertex][j]; //inserez un element in set
					s.insert(mp(d[son], son));
					count++;
				}
				else
					if (d[son] > d[vertex] + cost[vertex][j]) { //updatez un element din set
						MYSET::iterator it2 = s.find(mp(d[son], son));
						s.erase(it2);
						
						d[son] = d[vertex] + cost[vertex][j];
						s.insert(mp(d[son], son));
					}
			}
		}
		
		for (int j = 0; j < k; j++)
			road[i][j] = d[c[j]];
	}
}

void solve() {
	//gasesc distanta intre perechile de puncte de interes
	get_dist();
	
	//din descrierea sub forma de arbore df, stiu ca solutia va fi maxim 2 * suma_costurilor_muchiilor
	//sol[i][j] = costul minim daca am rezolvat configuratia j, si ultimul element ales este c[i]
	for (int i = 0; i < MAX_K; i++)
		for (int j = 0; j < MAX_P2; j++)
			sol[i][j] = inf;
	
	sol[0][1] = 0;
	for (int j = 0; j < (1 << k) - 1; j++)
		for (int i = 0; i < k; i++)
			if (sol[i][j] != inf) {
				for (int t = 0; t < k; t++)
					if ((j & (1 << t)) == 0) {
						int new_j = j + (1 << t);
						if (sol[t][new_j] > sol[i][j] + road[i][t])
							sol[t][new_j] = sol[i][j] + road[i][t];
					}
			}
	
	printf("%d\n", sol[k - 1][(1 << k) - 1]);
}

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", &c[i]);
	c[k++] = 1; c[k++] = n;
	
	sort(c, c + k);
	
	for (int i = 1; i <= m; i++) {
		int x, y, val;
		scanf("%d %d %d", &x, &y, &val);
		G[x].push_back(y); cost[x].push_back(val);
		G[y].push_back(x); cost[y].push_back(val);
	}
	
	solve();
	
	return 0;
}