#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#include <climits>
const int MAX_K = 15;
const int MAX_N = 2000;
struct Edge {
int u;
int cost;
bool operator <(const Edge &other) const {
return this->cost > other.cost;
}
};
int c[5 + MAX_K];
int distMin[5 + MAX_N][5 + MAX_N];
bool viz[5 + MAX_N];
int costMin[5 + 1 << MAX_K][MAX_K];
std::vector<Edge> g[5 + MAX_K];
void dijkstra(int node) {
memset(viz, false, sizeof(viz));
std::priority_queue<Edge> pq;
pq.push({node, 0});
while (!pq.empty()) {
Edge top = pq.top();
pq.pop();
int u = top.u;
if (!viz[u]) {
viz[u] = true;
distMin[node][u] = top.cost;
for (auto e : g[u]) {
if (!viz[e.u]) {
pq.push({e.u, top.cost + e.cost});
}
}
}
}
}
void preCalc(int N) {
for (int i = 0; i <= N; i++) {
dijkstra(c[i]);
}
}
int main() {
freopen ("ubuntzei.in", "r", stdin);
freopen ("ubuntzei.out", "w", stdout);
int N, M, K;
scanf("%d%d%d", &N, &M, &K);
for (int i = 1; i <= K; i++) {
scanf("%d", &c[i]);
}
c[0] = 1;
c[K + 1] = N;
for (int i = 1; i <= M; i++) {
int u, v, cost;
scanf("%d%d%d", &u, &v, &cost);
g[u].push_back({v, cost});
g[v].push_back({u, cost});
}
preCalc(K + 1);
if (K == 0) {
printf("%d\n", distMin[1][N]);
return 0;
}
for (int i = 1; i <= K; i++) {
costMin[1 << (i - 1)][i] = distMin[1][c[i]];
}
int lim = 1 << K;
for (int orase = 1; orase < lim; orase++) {
for (int i = 1; i <= K; i++) {
if (orase & (1 << (i - 1))) {
if (costMin[orase][i] != 0) {
continue;
}
costMin[orase][i] = INT_MAX;
for (int j = 1; j <= K; j++) {
if (i != j && orase & (1 << (j - 1))) {
costMin[orase][i] = std::min(costMin[orase][i], costMin[orase ^ (1 << (i - 1))][j] + distMin[c[j]][c[i]]);
}
}
}
}
}
int ans = INT_MAX;
for (int i = 1; i <= K; i++) {
ans = std::min(ans, costMin[lim - 1][i] + distMin[c[i]][N]);
}
printf("%d\n", ans);
return 0;
}