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

typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef pair<int,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const int INF=1000000000;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

struct UF{
	int par[100010],r[100010];
	void init(){
		rep(i,100010){
			par[i] = i;
			r[i] = 0;
		}
	}
	int find(int x){
		if(par[x] == x)return x;
		return par[x] = find(par[x]);
	}
	bool same(int x,int y){
		return find(x) == find(y);
	}
	void unit(int x,int y){
		if(same(x,y))return;
		x = find(x);
		y = find(y);
		if(r[x] < r[y]){
			par[x] = y;
		}
		else {
			par[y] = x;
			if(r[x] == r[y]){
				r[x] ++;
			}
		}
	}
}uf;

int n;
int cost[100010][20];
vector<int> G[100010];

int par[100010][20];
int dep[100010];

void dfs(int v,int p,int d){
	par[v][0] = p;
	dep[v] = d;
	rep(i,G[v].size()){
		if(G[v][i] == p)continue;
		dfs(G[v][i],v,d+1);
	}
}

void LCA_init(){
	rep1(j,19){
		rep1(i,n){
			par[i][j] = par[par[i][j-1]][j-1];
		}
	}
}

int LCA(int v,int u){
	if(dep[v] < dep[u])swap(v,u);
	rrep(i,20){
		if(dep[par[v][i]] >= dep[u])v = par[v][i];
	}
	if(v == u)return v;
	rrep(i,20){
		if(par[v][i] != par[u][i]){
			v = par[v][i];
			u = par[u][i];
		}
	}
	return par[v][0];
}

void minimum_init(){
	rep1(j,19){
		rep1(i,n){
			cost[i][j] = min( cost[i][j-1] , cost[par[i][j-1]][j-1] );
		}
	}
}

int minimum(int v,int a){
	int ret = INF;
	rrep(i,20){
		if(dep[par[v][i]] >= dep[a]){
			ret = min ( ret , cost[v][i] );
			v = par[v][i];
		}
	}
	return min(ret,cost[a][0]);
}

int solver(int s,int t){
	int lca = LCA(s,t);
	return min( minimum(s,lca) , minimum(t,lca) );
}

int main(){
	static int m,k,q;
	static int a[200010],b[200010],l[200010];
	static int f[100010];
	static int s[100010],t[100010];
	scanf("%d%d%d%d",&n,&m,&k,&q);
	rep(i,m)scanf("%d%d%d",&a[i],&b[i],&l[i]);
	rep(i,k)scanf("%d",&f[i]);
	rep(i,q)scanf("%d%d",&s[i],&t[i]);
	
	static vector<P> G_[100010];
	rep(i,m){
		G_[a[i]].pb(P(b[i],l[i]));
		G_[b[i]].pb(P(a[i],l[i]));
	}
	static bool used[100010];
	static priority_queue<P,vector<P>,greater<P>> que;
	rep(i,100010){
		cost[i][0] = INF;
		used[i] = false;
	}
	rep(i,k){
		cost[f[i]][0] = 0;
		que.push(P(cost[f[i]][0],f[i]));
	}
	while(!que.empty()){
		P p = que.top(); que.pop();
		if(!used[p.sc]){
			rep(i,G_[p.sc].size()){
				P ed = G_[p.sc][i];
				if(cost[ed.fr][0] > cost[p.sc][0] + ed.sc){
					cost[ed.fr][0] = cost[p.sc][0] + ed.sc;
					que.push(P(cost[ed.fr][0],ed.fr));
				}
			}
			used[p.sc] = true;
		}
	}
	
	//cout <<"DEBUG" << endl;
	
	vector<P> V;
	rep1(i,n){
		V.pb(P(cost[i][0],i));
	}
	sor(V);
	rev(V);
	
	//cout << "DEBUG" << endl;
	
	rep(i,100010)used[i] = false;
	uf.init();
	rep(i,V.size()){
		int v = V[i].sc;
		used[v] = true;
		rep(j,G_[v].size()){
			if(used[G_[v][j].fr]){
				if(!uf.same(v,G_[v][j].fr)){
					G[v].pb(G_[v][j].fr);
					G[G_[v][j].fr].pb(v);
					uf.unit(v,G_[v][j].fr);
				}
			}
		}
	}
	
	//cout << "DEBUG" << endl;
	
	dfs(1,0,1);
	LCA_init();
	minimum_init();
	
	rep(i,q){
		printf("%d\n",solver(s[i],t[i]));
	}
	
	//----------------
	/*rep1(i,n){
		printf("%d ",cost[i][0]);
	}puts("");
	rep1(i,n){
		printf("%d ",par[i][0]);
	}*/
}

Measured memory_bytes: 38420