Cod sursa(job #180577)

Utilizator plastikDan George Filimon plastik Data 17 aprilie 2008 11:10:52
Problema Team Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.76 kb
// Team, Infoarena/Lot 2006
// http://infoarena.ro/problema/team

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <climits>
#include <cassert>

#include <list>
#include <set>
using namespace std;

const int NMAX = 512;
const int PMAX = 64;

int p, n, m;
list<pair<int, int> > Neighb[NMAX];

int Dist[NMAX][NMAX], Ans[PMAX][PMAX][NMAX];
int End[PMAX];
set<int> Cities;

void roy_floyd() {
	int k, i, j;

	for (k = 1; k <= n; ++ k)
		for (i = 1; i <= n; ++ i) {
			if (k == i)
				continue;
			for (j = 1; j <= n; ++ j) {
				if (Dist[i][k] == INT_MAX || Dist[k][j] == INT_MAX)
					continue;
				if (Dist[i][j] > Dist[i][k] + Dist[k][j])
					Dist[i][j] = Dist[i][k] + Dist[k][j];
			}
		}
}


bool Used[NMAX];
void dijkstra(int src) {
	int i;
	for (i = 1; i <= n; ++ i) {
		Dist[src][i] = INT_MAX;
		Used[i] = false;
	}

	Dist[src][src] = 0;
	
	int nVis, curr = src, next, min;
	list<pair<int, int> >::iterator li;

	for (nVis = 1; nVis <= n; ++ nVis) {
		assert(Dist[src][curr] != INT_MAX);

		min = INT_MAX, next = -1;
		for (i = 1; i <= n; ++ i)
			if (Used[i] != true && Dist[src][i] < min) {
				min = Dist[src][i];
				next = i;
			}

		assert(next != -1);

		for (li = Neighb[next].begin(); li != Neighb[next].end(); ++ li)
			if (Dist[src][next] + li->second < Dist[src][li->first])
				Dist[src][li->first] = Dist[src][next] + li->second;
		
		curr = next;
		Used[curr] = true;
	}
}

int main() {

	freopen("team.in", "r", stdin);
	freopen("team.out", "w", stdout);

	scanf("%d %d %d", &p, &n, &m);
	int i, j, v1, v2, c;

	for (i = 1; i <= n; ++ i)
		for (j = 1; j <= n; ++ j)
			Dist[i][j] = INT_MAX;
	for (i = 1; i <= n; ++ i)
		Dist[i][i] = 0;

	for (i = 0; i < m; ++ i) {
		scanf("%d %d %d", &v1, &v2, &c);
		Neighb[v1].push_back(make_pair(v2, c));
		Neighb[v2].push_back(make_pair(v1, c));
		Dist[v1][v2] = Dist[v2][v1] = c;
	}
	for (i = 1; i <= p; ++ i) {
		scanf("%d", &End[i]);
		Cities.insert(End[i]);
	}
	Cities.insert(1);

	//roy_floyd();

	set<int>::iterator si;
	for (si = Cities.begin(); si != Cities.end(); ++ si) 
		dijkstra(*si);

	int k, l, ans;

	for (l = 1; l <= p; ++ l)
		for (i = 1; i <= p - l + 1; ++ i)
			for (si = Cities.begin(); si != Cities.end(); ++ si)
				Ans[i][i + l - 1][*si] = INT_MAX;

	for (i = 1; i <= p; ++ i)
		for (j = 1; j <= n; ++ j)
			Ans[i][i][j] = Dist[j][End[i]];

	for (l = 2; l <= p; ++ l)
		for (i = 1; i <= p - l + 1; ++ i) {
			j = i + l - 1;
			for (si = Cities.begin(); si != Cities.end(); ++ si) {
				ans = INT_MAX;
				for (k = i; k <= j; ++ k) {
					if (Ans[i][k - 1][End[k]] == INT_MAX ||  Ans[k + 1][j][End[k]] == INT_MAX || Dist[*si][End[k]] == INT_MAX)
						continue;
					ans = min(ans, Ans[i][k - 1][End[k]] + Ans[k + 1][j][End[k]] + Dist[*si][End[k]]);
				}
				Ans[i][j][*si] = ans;
			}
		}

	printf("%d\n", Ans[1][p][1]);

	return 0;
}