Cod sursa(job #176890)

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

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <cstring>
#include <climits>
#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], Used[NMAX];
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];
			}
		}
}*/

void dijkstra(int src) {
	int i, j, curr, next, ans;
	list<pair<int, int> >::iterator li;

	memset(Used, false, sizeof(Used));
	Used[src] = true;
	curr = src;
	for (i = 1; i <= n; ++ i) {
		ans = INT_MAX;
		for (j = 1; j <= n; ++ j)
			if (Used[j] == false && ans > Dist[src][j]) {
				ans = Dist[src][j];
				curr = j;
			}

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

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);

	/*for (i = 1; i <= n; ++ i)
		dijkstra(i);*/
	dijkstra(1);
	for (i = 1; i <= p; ++ i)
		dijkstra(End[i]);
	//roy_floyd();

	set<int>::iterator 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;
}