#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
#include <sstream>
using namespace std;

typedef long long int64;
const int inf = (int)1e9;

typedef vector<vector<pair<int, int> > > graph;

struct UnionFind {
	
	int size;
	vector<int> par;
	
	UnionFind(int s)
	{
		size = s;
		par.resize(size);
		for(int i = 0; i < size; ++i)
			par[i] = i;
	}
	
	int root(int a)
	{
		if(par[a] == a)
			return a;
		return par[a] = root(par[a]);
	}
	
	bool same(int a, int b)
	{
		return root(a) == root(b);
	}
	
	void unite(int a, int b)
	{
		a = root(a);
		b = root(b);
		par[a] = b;
	}
};

int main()
{
	int n, m, k, qn;
	graph gg, g;
	vector<pair<int, pair<int, int> > > e;
	
	scanf("%d%d%d%d", &n, &m, &k, &qn);
	gg.resize(n), g.resize(n), e.resize(m);
	
	for(int i = 0; i < m; ++i) {
		int a, b, l;
		scanf("%d%d%d", &a, &b, &l);
		a -= 1, b -= 1;
		gg[a].push_back(make_pair(b, l));
		gg[b].push_back(make_pair(a, l));
		e[i] = make_pair(0, make_pair(a, b));
	}
	
	vector<int> dist;
	priority_queue<pair<int, int> > q;
	
	dist.resize(n, inf);
	
	for(int i = 0; i < k; ++i) {
		int f;
		scanf("%d", &f);
		f -= 1;
		q.push(make_pair(0, f));
	}
	
	while(!q.empty()) {
		
		int c = -q.top().first;
		int v = q.top().second;
		q.pop();
		
		if(dist[v] < c)
			continue;
		dist[v] = c;
		
		for(int i = 0; i < gg[v].size(); ++i) {
			int w = gg[v][i].first;
			int nextc = c + gg[v][i].second;
			q.push(make_pair(-nextc, w));
		}
	}
	
	for(int i = 0; i < m; ++i) {
		int a = e[i].second.first, b = e[i].second.second;
		e[i].first = min(dist[a], dist[b]);
	}
	sort(e.rbegin(), e.rend());
	
	UnionFind uf(n);
	
	for(int i = 0; i < m; ++i) {
		int cost = e[i].first;
		int a = e[i].second.first, b = e[i].second.second;
		if(uf.same(a, b))
			continue;
		g[a].push_back(make_pair(b, cost));
		g[b].push_back(make_pair(a, cost));
		uf.unite(a, b);
	}
	
	const int maxhop = 20;
	vector<pair<int, int> > parlink[maxhop];
	vector<int> num;
	
	for(int i = 0; i < maxhop; ++i)
		parlink[i].resize(n);
	num.resize(n, inf);
	
	stack<pair<int, int> > s;
	s.push(make_pair(0, 0));
	while(!s.empty()) {
		int v = s.top().first;
		int l = s.top().second;
		s.pop();
		num[v] = l;
		for(int i = 0; i < g[v].size(); ++i) {
			int w = g[v][i].first;
			if(num[v] < num[w])
				s.push(make_pair(w, l + 1));
		}
	}
	
	for(int i = 0; i < n; ++i) {
		
		int par = i;
		int l = dist[i];
		for(int j = 0; j < g[i].size(); ++j) {
			int w = g[i][j].first;
			if(num[w] < num[i]) {
				par = w;
				l = g[i][j].second;
			}
		}
		parlink[0][i] = make_pair(par, l);
	}
	
	for(int step = 1; step < maxhop; ++step) {
		for(int i = 0; i < n; ++i) {
		
			int par = parlink[step - 1][i].first;
			int cost = parlink[step - 1][i].second;
			cost = min(cost, parlink[step - 1][par].second);
			par = parlink[step - 1][par].first;
			parlink[step][i] = make_pair(par, cost);
		}
	}
	
	for(int count = 0; count < qn; ++count) {
		
		int s, t;
		
		scanf("%d%d", &s, &t);
		s -= 1, t -= 1;
		
		if(num[s] < num[t])
			swap(s, t);
		
		int diff = num[s] - num[t];
		int ans = min(dist[s], dist[t]);
		
		for(int i = maxhop - 1; i >= 0; --i) {
			if(diff & (1 << i)) {
				ans = min(ans, parlink[i][s].second);
				s = parlink[i][s].first;
			}
		}
		
		if(s != t) {
		
			for(int step = maxhop - 1; step >= 0; --step) {
				
				bool down = parlink[step][s].first != parlink[step][t].first;
				
				if(down) {
					ans = min(ans, min(parlink[step][s].second, parlink[step][t].second));
					s = parlink[step][s].first;
					t = parlink[step][t].first;
				}
			}
			
			ans = min(ans, min(parlink[0][s].second, parlink[0][t].second));
		}
		
		printf("%d\n", ans);
	}
	
	return 0;
}

/* ハラスメントに負けず */
/* 0完太陽にも負けず */
/* はやく人権を獲得したい */
/* nullmineralが書きましたが */
/* 責任はまったくとりません */

Measured memory_bytes: 35520