#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef   long long int ll;
typedef long double db;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define ub(v,val) upper_bound(v.begin(),v.end(),val)
#define np(str) next_permutation(str.begin(),str.end())
#define lb(v,val) lower_bound(v.begin(),v.end(),val)
#define sortv(vec) sort(vec.begin(),vec.end())
#define rev(p) reverse(p.begin(),p.end());
#define v vector
#define pi 3.14159265358979323846264338327950288419716939937510
#define len length()
#define repc(i,s,e) for(ll i=s;i<e;i++)
#define fi first
#define se second
#define mset(a,val) memset(a,val,sizeof(a));
#define mt make_tuple
#define repr(i,n) for(i=n-1;i>=0;i--)
#define rep(i,n) for(i=0;i<n;i++)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define at(s,pos) *(s.find_by_order(pos))
#define set_ind(s,val) s.order_of_key(val)
long long int M = 1e9 + 7 ;
long long int inf = 9 * 1e18;
//CLOCK
ll begtime = clock();
#define time() cout << "\n\nTime elapsed: " << (clock() - begtime)*1000/CLOCKS_PER_SEC << " ms\n\n";
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//CLOCK ENDED
ll n, m;
// modular exponentiation
ll binpow(ll val, ll deg)
{
	if (deg < 0)
		return 0;
	if (!deg)
		return 1 % M;
	if (deg & 1)
		return binpow(val, deg - 1) * val % M;
	ll res = binpow(val, deg >> 1);
	return (res * res) % M;
}
//binomial
ll modinv(ll n) {
	return binpow(n, M - 2);
}

v<v<ll>> adj;
int main() {
	// your code goes here
	IOS;
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ll i, j, t, k, x, y, z,  N;
	cin >> n >> m;
	adj.resize(n);
	rep(i, m) {
		cin >> x >> y;
		x--; y--;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	cin >> k;
	ll c[k];
	rep(i, k) {cin >> c[i]; c[i]--;}
	ll dis[k][n];
	rep(i, k) {
		rep(j, n) {
			dis[i][j] = inf;
		}
	}
	rep(i, k) {
		dis[i][c[i]] = 0;
		queue<ll> q;
		v<ll> used(n, 0);
		ll s = c[i];
		q.push(s);
		used[s] = 1;
		while (!q.empty())
		{
			ll V = q.front();
			q.pop();
			for (ll u : adj[V])
			{
				if (!used[u])
				{
					used[u] = 1;
					dis[i][u] = dis[i][V] + 1;
					q.push(u);
				}
			}
		}

	}
	ll cost[1LL << k][k];
	// cout << k;
	rep(i, 1LL << k) {
		rep(j, k) {
			cost[i][j] = inf;
		}
	}
	rep(i, k) {
		cost[1LL << i][i] = 0;
	}
	for (i = 1LL; i < (1LL << k); i++) {
		v<ll> vec;
		rep(j, k) {
			if ((1LL << j)&i)vec.pb(j);
		}
		rep(j, k) {
			if (!((1 << j)&i)) {
				for (auto u : vec) {
					if (dis[u][c[j]] != inf && cost[i][u] != inf)
						cost[i | (1LL << j)][j] = min(cost[i | (1LL << j)][j], dis[u][c[j]] - 1LL + cost[i][u]);
				}
			}
		}
	}
	ll mn = inf;
	rep(i, k) {
		mn = min(mn, cost[(1LL << k) - 1LL][i]);
	}
	if (mn == inf)cout << -1LL;
	else {
		cout << mn + k;

	}

	return 0;




}









#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <cmath>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <iomanip>
using namespace std;

using VI = vector <int>;
using VVI = vector <VI>;
using VVVI = vector <VVI>;
using VLL = vector <long long>;
using VVLL = vector <VLL>;
using VVVLL = vector <VVLL>;
using UMI = unordered_map<int, int>;
using UMLL = unordered_map<long long, long long>;

struct Que {
    int now;
    long long dist;

    Que (int pn, long long pd) : now(pn), dist(pd) {}

    bool operator<(const Que& q) const {
        return dist > q.dist;
    }
};

long long lowVal(long long val, long long target) {
    if (target == 0) {
        return val+1;
    }

    long long low = 1;
    long long up = val;
    long long ret = val;

    while (low <= up) {
        long long mid = (low+up) / 2;
        long long d = val / mid;

        if (d >= target) {
            low = mid+1;
            ret = mid;
        } else {
            up = mid-1;
        }
    }

    return ret;
}

int main() {
    int N;
    int M;

    cin >> N >> M;
    VVVLL adja(N);

    for (int i = 0; i < M; ++i) {
        int a;
        int b;
        int c;
        int d;
        cin >> a >> b >> c >> d;
        --a;
        --b;

        adja[a].push_back({b, c, d});
        adja[b].push_back({a, c, d});
    }

    const long long INF = 1000000000LL * 100000000LL;
    VLL dp(N, INF);
    VI used(N);
    priority_queue <Que> pq;
    dp[0] = 0;
    pq.push(Que(0, 0));

    while (!pq.empty()) {
        Que tq = pq.top();
        int now = tq.now;
        pq.pop();

        // cout << "DEBUG " << now << " " << dp[now] << endl;

        if (used[now]) {
            continue;
        }

        used[now] = 1;
        long long nt = dp[now];

        for (int i = 0; i < adja[now].size(); ++i) {
            int nextv = adja[now][i][0];
            long long C = adja[now][i][1];
            long long D = adja[now][i][2];

            // cost = dt + (C + (D/(nt+1+dt)))
            long long low = 0;
            long long up = nt ? D/nt : D;
            auto costCal = [&nt, &C, &D](long long dt) { return nt+dt+(C+D/(nt+1+dt)); };
            long long best = costCal(0);

            // 0 = 1 - D/(nt+1+dt)^2
            // D = (nt+1+dt)^2
            // sqrt(D)-nt-1

            long long base = sqrt(D)-nt-1;
            for (long long vdt = max(0LL, base-10); vdt <= base+10; ++vdt) {
                best = min(best, costCal(vdt));
            }

            // cerr << now << " " << nextv << " BEST " << best << endl;
            if (best < dp[nextv]) {
                dp[nextv] = best;
                pq.push(Que(nextv, best));
            }
        }
    }

    cout << (dp[N-1] == INF ? -1 : dp[N-1]) << endl;

    return 0;
}