Problem:
Score : 400 points

Problem Statement

There are N towns in the State of Atcoder, connected by M bidirectional roads.

The i-th road connects Town A_i and B_i and has a length of C_i.

Joisino is visiting R towns in the state, r_1,r_2,..,r_R (not necessarily in this order).

She will fly to the first town she visits, and fly back from the last town she visits, but for the rest of the trip she will have to travel by road.

If she visits the towns in the order that minimizes the distance traveled by road, what will that distance be?

Constraints

2≤N≤200

1≤M≤N×(N-1)/2

2≤R≤min(8,N) (min(8,N) is the smaller of 8 and N.)

r_i≠r_j (i≠j)

1≤A_i,B_i≤N, A_i≠B_i

(A_i,B_i)≠(A_j,B_j),(A_i,B_i)≠(B_j,A_j) (i≠j)

1≤C_i≤100000

Every town can be reached from every town by road.

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M R
r_1 ... r_R
A_1 B_1 C_1
:
A_M B_M C_M

Output

Print the distance traveled by road if Joisino visits the towns in the order that minimizes it.

Sample Input 1

3 3 3
1 2 3
1 2 1
2 3 1
3 1 4

Sample Output 1

2

For example, if she visits the towns in the order of 1, 2, 3, the distance traveled will be 2, which is the minimum possible.

Sample Input 2

3 3 2
1 3
2 3 2
1 3 6
1 2 2

Sample Output 2

4

The shortest distance between Towns 1 and 3 is 4. Thus, whether she visits Town 1 or 3 first, the distance traveled will be 4.

Sample Input 3

4 6 3
2 3 4
1 2 4
2 3 3
4 3 1
1 4 1
4 2 2
3 1 6

Sample Output 3

3

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_ON			1										// 汎用フラグ - ON
#define D_OFF			0										// 汎用フラグ - OFF
#define D_TOWN_MAX		200										// 最大町数
#define D_VISIT_MAX		8										// 最大訪問町数

// 内部構造体 - 町情報
typedef struct Town {
	int mi1TNo[D_TOWN_MAX];										// 隣接町 1～
	int mi1Len[D_TOWN_MAX];										// 隣接町までの距離
	int miTCnt;													// 隣接町数
	int miMin;													// 特定の町からの最短距離
} Town;

// 内部構造体 - ヒープ情報
typedef struct Heap {
	int miTNo;													// 隣接町 1～
	int miLen;													// 隣接町までの累計距離
} Heap;

// 内部変数
static Town sz1Town[D_TOWN_MAX + 5];							// 町情報
static int siTCnt;												// 町情報数
static int si1Visit[D_VISIT_MAX];								// 訪問町
static int siVCnt;												// 訪問町数
static Heap sz1Heap[D_TOWN_MAX * D_TOWN_MAX];					// ヒープ
static int siHCnt;												// ヒープ数
static int si2Min[D_VISIT_MAX + 5][D_VISIT_MAX + 5];			// 訪問町間の最短距離
static int siMin;												// 全訪問の最短距離

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpT, *szpFpA;
#endif

// 隣接町情報をセット
int
fSetTown(
	int piTNo1					// <I> 町情報１ 1～
	, int piTNo2				// <I> 町情報２ 1～
	, int piLen					// <I> 距離
)
{
	// 対象データ
	Town *lzpTown = &sz1Town[piTNo1];

	// セット
	lzpTown->mi1TNo[lzpTown->miTCnt] = piTNo2;		// 隣接町
	lzpTown->mi1Len[lzpTown->miTCnt] = piLen;		// 隣接町までの距離
	lzpTown->miTCnt++;								// 隣接町数
	
	return 0;
}

// ヒープ - 親子関係チェック
// 戻り値：[>=0]:変更した子の配列番号 [-1]:変更なし
int
fHeapChk(
	int piPNo					// <I> 親の配列番号 0～
)
{
	// 最小値
	int liMNo = piPNo;

	// 左の子と比較
	int liCNo = piPNo * 2 + 1;
	if (liCNo < siHCnt) {
		if (sz1Heap[liMNo].miLen > sz1Heap[liCNo].miLen) {
			liMNo = liCNo;
		}
	}

	// 右の子と比較
	liCNo = piPNo * 2 + 2;
	if (liCNo < siHCnt) {
		if (sz1Heap[liMNo].miLen > sz1Heap[liCNo].miLen) {
			liMNo = liCNo;
		}
	}

	// 自分が最小値であるかチェック
	if (piPNo == liMNo) {
		return -1;
	}

	// 値の交換
	Heap lzWork;
	memcpy(&lzWork, &sz1Heap[liMNo], sizeof(Heap));
	memcpy(&sz1Heap[liMNo], &sz1Heap[piPNo], sizeof(Heap));
	memcpy(&sz1Heap[piPNo], &lzWork, sizeof(Heap));

	return liMNo;
}

// ヒープ - キュー追加
int
fHeapEnqueue(
	int piTNo					// <I> 隣接町 1～
	, int piLen					// <I> 隣接町までの累計距離
)
{
	int liRet;

	// 末尾に追加
	sz1Heap[siHCnt].miTNo = piTNo;
	sz1Heap[siHCnt].miLen = piLen;
	siHCnt++;

	// 親子関係チェック
	int liNo = siHCnt - 1;
	while (1) {

		// 親の配列番号
		liNo = (liNo - 1) / 2;

		// 親子関係チェック
		liRet = fHeapChk(liNo);
		if (liRet < 0) {
			break;
		}
	}

	return 0;
}

// ヒープ - キュー取得
int
fHeapDequeue(
	Heap *pzpRet				// <O> 取得先
)
{
	// データ数
	if (siHCnt < 1) {
		return -1;
	}

	// 取得
	memcpy(pzpRet, &sz1Heap[0], sizeof(Heap));
	siHCnt--;

	// データ数
	if (siHCnt < 1) {
		return 0;
	}

	// 末尾を先頭へ
	memcpy(&sz1Heap[0], &sz1Heap[siHCnt], sizeof(Heap));

	// 親子関係チェック
	int liNo = 0;
	while (liNo >= 0) {
		liNo = fHeapChk(liNo);
	}

	return 0;
}

// 特定の町からの最短距離をセット
int
fSetTownMin(
)
{
	int i, liRet;

	while (1) {

		// キュー取得
		Heap lzHeap;
		liRet = fHeapDequeue(&lzHeap);
		if (liRet != 0) {
			break;
		}

		// 対象データ
		Town *lzpTown = &sz1Town[lzHeap.miTNo];

		// セット済みかチェック
		if (lzpTown->miMin >= 0) {
			continue;
		}

		// セット
		lzpTown->miMin = lzHeap.miLen;

		// ヒープ追加
		for (i = 0; i < lzpTown->miTCnt; i++) {
			fHeapEnqueue(lzpTown->mi1TNo[i], lzpTown->miMin + lzpTown->mi1Len[i]);
		}
	}

	return 0;
}

// 訪問町間の最短距離をセット
int
fSetVisit(
	int piVNo					// <I> 訪問町 0～
)
{
	int i;

	// 特定の町からの最短距離を初期化
	for (i = 1; i <= siTCnt; i++) {
		sz1Town[i].miMin = -1;
	}

	// 特定の町からの最短距離をセット
	fHeapEnqueue(si1Visit[piVNo], 0);		// キュー追加
	fSetTownMin();

	// 訪問町間の最短距離をセット
	for (i = 0; i < siVCnt; i++) {
		if (i != piVNo) {
			si2Min[piVNo][i] = sz1Town[si1Visit[i]].miMin;
		}
	}

	return 0;
}

// 全訪問の最短距離をセット
int
fSetMin(
	int piVNo					// <I> 現在位置
	, int *pipVNo				// <I> 訪問済町
	, int piVCnt				// <I> 訪問済町数
	, int piLen					// <I> 距離
)
{
	int i;

	// 訪問済チェック
	if (pipVNo[piVNo] != D_OFF) {
		return 0;
	}

	// 訪問完了
	if (piVCnt == siVCnt - 1) {

		// 全訪問の最短距離更新
		if (siMin > piLen) {
			siMin = piLen;
		}

		return 0;
	}

	// 訪問
	pipVNo[piVNo] = D_ON;

	// 次の町へ
	for (i = 0; i < siVCnt; i++) {
		fSetMin(i, pipVNo, piVCnt + 1, piLen + si2Min[piVNo][i]);
	}

	// 訪問解除
	pipVNo[piVNo] = D_OFF;

	return 0;
}

// 実行メイン
int
fMain(
	int piTNo					// <I> テスト番号 1～
)
{
	int i;
	char lc1Buf[1024], lc1Out[1024];

	// データ初期化
	memset(sz1Town, 0, sizeof(sz1Town));						// 町情報
	siHCnt = 0;													// ヒープ数
	siMin = INT_MAX;											// 全訪問の最短距離

	// テストファイルオープン
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", piTNo);
	szpFpT = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", piTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#endif

	// 町数・道路数・訪問町数取得
	int liRCnt;
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpT);
#else
	fgets(lc1Buf, sizeof(lc1Buf), stdin);
#endif
	sscanf(lc1Buf, "%d%d%d", &siTCnt, &liRCnt, &siVCnt);

	// 訪問町取得
	for (i = 0; i < siVCnt; i++) {
#ifdef D_TEST
		fscanf(szpFpT, "%d", &si1Visit[i]);
#else
		fscanf(stdin, "%d", &si1Visit[i]);
#endif
	}
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpT);
#else
	fgets(lc1Buf, sizeof(lc1Buf), stdin);
#endif

	// 道路取得
	for (i = 0; i < liRCnt; i++) {
		int liTNo1, liTNo2, liLen;
#ifdef D_TEST
		fgets(lc1Buf, sizeof(lc1Buf), szpFpT);
#else
		fgets(lc1Buf, sizeof(lc1Buf), stdin);
#endif
		sscanf(lc1Buf, "%d%d%d", &liTNo1, &liTNo2, &liLen);

		// 隣接町情報をセット
		fSetTown(liTNo1, liTNo2, liLen);
		fSetTown(liTNo2, liTNo1, liLen);
	}

	// 訪問町間の最短距離をセット
	for (i = 0; i < siVCnt; i++) {
		fSetVisit(i);
	}

	// 全訪問の最短距離をセット
	int li1VNo[D_VISIT_MAX];
	memset(li1VNo, D_OFF, sizeof(li1VNo));
	for (i = 0; i < siVCnt; i++) {
		fSetMin(i, li1VNo, 0, 0);
	}

	// 結果セット
	sprintf(lc1Out, "%d\n", siMin);

	// 結果表示
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, lc1Out)) {
		siRes = -1;
	}
#else
	printf("%s", lc1Out);
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpT);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", piTNo);
	}
	else {
		printf("NG %d\n", piTNo);
	}
#endif

	return 0;
}

int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		fMain(i);
	}
#else
	fMain(0);
#endif

	return 0;
}