#define _CRT_SECURE_NO_WARNINGS
#include "bits/stdc++.h"
using namespace std;

#define int long long

#define CHOOSE(a) CHOOSE2 a
#define CHOOSE2(a0,a1,a2,a3,x,...) x
#define REP1(i, s, cond, cal) for (signed i = signed(s); i cond; i cal)
#define REP2(i, s, n) REP1(i, s, < signed(n), ++)
#define REP3(i, n) REP2(i, 0, n)
#define rep(...) CHOOSE((__VA_ARGS__,REP1,REP2,REP3))(__VA_ARGS__)
#define rrep(i, s) rep(i, s, >= 0, --)

#define all(c) begin(c), end(c)

#define X first
#define Y second

using VV = vector<vector<int>>;
using V = vector<int>;
using P = pair<int, int>;
using IP = pair<int, P>;

template<typename T>
inline void input(vector<T>& v) { for (auto& x : v) cin >> x; }

vector<vector<P>> graph;
vector<int> fests;
vector<vector<P>> qs;
vector<int> anses;
vector<int> fdists;

struct UnionFind {

	int n;
	vector<int> data;
	vector<int> sums;
	UnionFind(int n) : n(n) {
		data.resize(n, -1);
		sums.resize(n);
	}
	int unite(int a, int b) {
		int x = find(a), y = find(b);
		if (x != y) {
			if (sum(x) < sum(y)) swap(x, y);
			for (P p : qs[y]) qs[x].push_back(p);
			qs[y].clear();
			data[x] = -min(-data[x], -data[y]);
			sums[x] += sums[y];
			data[y] = x;
			return -data[x];
		} else return -1;
	}
	int find(int a) {
		return data[a] < 0 ? a : data[a] = find(data[a]);
	}
	bool same(int a, int b) { return find(a) == find(b); }
	int mini(int a) {
		return -data[find(a)];
	}
	int sum(int a) {
		return sums[find(a)];
	}
};

signed main() {
	int N, M, K, Q; cin >> N >> M >> K >> Q;

	graph.resize(N);
	fests.resize(K);
	anses.resize(Q, -1);
	fdists.resize(N, 1 << 29);
	qs.resize(N);

	rep(i, M) {
		int a, b, l; cin >> a >> b >> l;
		a--; b--;
		graph[a].push_back({ l, b });
		graph[b].push_back({ l, a });
	}
	rep(i, K) {
		int f; cin >> f;
		f--;
		fests[i] = f;
	}
	rep(i, Q) {
		int s, t; cin >> s >> t;
		s--; t--;
		qs[s].push_back({ t, i });
		qs[t].push_back({ s, i });
	}

	priority_queue<P, vector<P>, greater<P>> pque;
	rep(i, K) {
		pque.push({ 0, fests[i] });
		fdists[fests[i]] = 0;
	}
	while (!pque.empty()) {
		P pre = pque.top(); pque.pop();
		int pd = pre.first, pn = pre.second;
		if (fdists[pn] < pd) continue;
		for (P p : graph[pn]) {
			int nd = pd + p.first, to = p.second;
			if (fdists[to] <= nd) continue;
			fdists[to] = nd;
			pque.push({ nd, to });
		}
	}

	vector<P> dists;
	rep(i, N) dists.push_back({ fdists[i], i });
	sort(all(dists));
	reverse(all(dists));

	UnionFind uf(N);
	priority_queue<IP> que;
	rep(i, N) {
		uf.data[i] = -fdists[i] - 1;
		uf.sums[i] = qs[i].size();
		que.push({ fdists[i], {i, i} });
	}

	while (!que.empty()) {
		IP ip = que.top(); que.pop();
		int pd = ip.first, from = ip.second.first, to = ip.second.second;
		if (from != to && uf.same(from, to)) continue;
		if (from != to) {
			//???????????????
			//???????????¨????????????????????????????????????????????¨?????????
			int a = uf.find(from), b = uf.find(to);
			if (uf.sum(a) > uf.sum(b)) swap(a, b);
			int ans = min(uf.mini(a), uf.mini(b)) - 1;
			for (P p : qs[a]) {
				int c = p.first, idx = p.second;
				if (anses[idx] != -1 || !(uf.same(a, c) || uf.same(b, c))) continue;
				anses[idx] = ans;
			}
			uf.unite(from, to);
		}

		for (P p : graph[to]) if (!uf.same(to, p.second)) {
			int next = p.second;
			int nc = min(uf.mini(next), uf.mini(to));
			que.push({ nc, {to,next} });
		}
	}

	for (auto x : anses) {
		cout << x << endl;
	}

	//system("pause");
}

Measured memory_bytes: 47076