#include <bits/stdc++.h>
using namespace std;

using Int = long long;
#define PUTS(x) std::cout << (x) << endl;
#define rep(i, n) for (int i = 0, i##_len = (int)(n); i < i##_len; i++)
#define rep3(i, m, n) for (int i = (int)(m), i##_len = (int)(n); i < i##_len; i++)

template <typename T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

const Int INF = 1000000000;

struct Node {
    vector<Int> to;
    Int dist = INF;
};

int main() {
    Int n, m;
    cin >> n >> m;

    auto G = vector<Node>(n);

    rep(i, m) {
        Int a, b;
        cin >> a >> b;
        a--;
        b--;
        G[a].to.push_back(b);
        G[b].to.push_back(a);
    }

    Int k;
    cin >> k;
    auto C = vector<Int>();
    rep(i, k) {
        Int c;
        cin >> c;
        c--;
        C.push_back(c);
    }

    auto M = 1;
    rep(i, k) {
        M *= 2;
    }

    // d[i][j]: C[i] -> C[j] の最短距離 を記録
    auto d = vector<vector<Int>>(k, vector<Int>(k, 0));
    rep(i, k - 1) {
        auto g = G;
        g[C[i]].dist = 0;
        auto q = queue<Int>();
        q.push(C[i]);
        while (!q.empty()) {
            auto j = q.front();
            auto &node = g[j];
            q.pop();
            for (auto p : node.to) {
                auto oldValue = g[p].dist;
                auto newValue = g[j].dist + 1;
                if (newValue < oldValue) {
                    g[p].dist = newValue;
                    q.push(p);
                }
            }
        }
        rep3(j, i + 1, k) {
            d[i][j] = g[C[j]].dist;
            d[j][i] = d[i][j];
        }
    }

    // dp[i][bits] : 既に訪れた頂点の集合が bits かつ今C[i]にいるという条件を満たす最小工程
    // bits は右からjビット目がC[j]を既に訪れていることを示す（C[i]自身も「既に訪れた」扱いにする）
    auto dp = vector<vector<Int>>(k, vector<Int>(M, INF));

    // 配るdp
    function<void(Int, Int)> dfs = [&](Int current, Int bits) {
        rep(i, k) {
            if (((1 << i) & bits) == 0) { // まだ訪れていないC[i]について
                auto nextBits = (1 << i) | bits; // C[i]を次に訪れた場合の bit flag
                auto oldValue = dp[i][nextBits];
                auto newValue = dp[current][bits] + d[current][i];
                if (newValue < oldValue) { // 最短記録が更新されたらそこから再度DFS
                    dp[i][nextBits] = newValue;
                    dfs(i, nextBits);
                }
            }
        }
    };

    // 初期値設定（C[i] のみの列はコスト1扱い）
    rep(i, k) {
        dp[i][1 << i] = 1;
    }
    // スタート
    rep(i, k) {
        dfs(i, 1 << i);
    }

    Int ans = INF;
    rep(i, k) {
        // M-1 = [11111...]_2  は全てのC[j]を訪れたフラグ。dp[i][M-1]は全てのC[j]を訪れて最後にC[i]に至る場合の最短列の長さを示す。
        chmin(ans, dp[i][M - 1]);
    }
    PUTS(ans == INF ? -1 : ans)
}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
const int maxk = 17;
const int maxs = (1 << maxk) + 10;
const int INF = 0x3f3f3f3f;
int n, m, k;
vector<int> E[maxn];
int c[maxk], dis[maxn], a[maxk][maxk], f[maxk][maxs];
void bfs(int x)
{
	memset(dis, 0x3f, sizeof dis);
	queue<int> Q;
	Q.push(x); dis[x] = 0;
	while(!Q.empty())
	{
		x = Q.front(); Q.pop();
		for(auto v : E[x])
			if(dis[v] == INF)
			{
				dis[v] = dis[x] + 1;
				Q.push(v);
			}
	}
}	 
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; ++i)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
	}
	scanf("%d", &k);
	for(int i = 0; i < k; ++i)
		scanf("%d", &c[i]);
	for(int i = 0; i < k; ++i)
	{
		bfs(c[i]);
		for(int j = 0; j < k; ++j)
			a[i][j] = dis[c[j]];
	}
	const int S = (1 << k) - 1;
	memset(f, 0x3f, sizeof f);
	for(int i = 0; i < k; ++i) f[i][1 << i] = 0;
	for(int s = 1; s <= S; ++s)
		for(int i = 0; i < k; ++i)
			if(s & (1 << i))
			{
				for(int j = 0; j < k; ++j)
					if(i != j && (s & (1 << j)))
						f[i][s] = min(f[i][s], f[j][s ^ (1 << i)] + a[j][i]);
			}
	int ans = INF;
	for(int i = 0; i < k; ++i)
		ans = min(ans, f[i][S] + 1);
	printf("%d\n", ans == INF ? -1 : ans);
	return 0;
}