#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>

using namespace std;

const int INF=1000000009;
struct edge{
	int t,c;
	edge(int t,int c):t(t),c(c){};
};
struct log{
	int c,f,t;
};
struct lca{
	int t,c;
};
typedef pair<int,int> P;
typedef pair<int,P> PP;
//入力
int N,M,K,Q;
int fest[100001];
//dijk&cruskal
int par[100001];
int rank[100001];
int dist[100001];
bool used[100001];
vector<edge> G[100001];
vector<log> all;
vector<edge> tree[100001];
//lca
int root;
int depth[100001];
lca parent[20][100001];


//lca
void dfs(int v,int p,int deep){
	parent[0][v].t=p;
	parent[0][v].c=min(dist[v],(p!=-1 ? dist[p]:INF));
	depth[v]=deep;
	for(int i=0;i<tree[v].size();i++){
		if(tree[v][i].t!=p){
			dfs(tree[v][i].t,v,deep+1);
		}
	}
}

void rmg_init(int V){
	dfs(root,-1,0);
	for(int k=0;k+1<20;k++){
		for(int v=0;v<V;v++){
			if(parent[k][v].t<0){
				parent[k+1][v].t=-1;
			}else{
				parent[k+1][v].t=parent[k][parent[k][v].t].t;
				parent[k+1][v].c=min(parent[k][parent[k][v].t].c,parent[k][v].c);
				
			}
		}
	}
}

int query(int u,int v){
	int res;
	res=min(dist[u],dist[v]);
	if(depth[u]>depth[v])swap(u,v);
	for(int k=0;k<20;k++){
		if(((depth[v]-depth[u]) >> k) & 1){
			res=min(res,parent[k][v].c);
			v=parent[k][v].t;
		}
	}
	if(u==v)return min(res,dist[u]);
	for(int k=19;k>=0;k--){
		if(parent[k][u].t!=parent[k][v].t){
			res=min(res,min(parent[k][u].c,parent[k][v].c));
			u=parent[k][u].t;
			v=parent[k][v].t;
		}
	}
	return (min(res,parent[0][v].c));
}

//dijkstra

void dijk(){
	fill(dist,dist+N,INF);
	priority_queue<P,vector<P>,greater<P> > que;
	for(int i=0;i<K;i++){
		que.push(P(0,fest[i]));
		dist[fest[i]]=0;
	}
	while(que.size()){
		P p=que.top();
		que.pop();
		int c=p.first,v=p.second;
		if(dist[v]<c)continue;
		for(int i=0;i<G[v].size();i++){
			edge e=G[v][i];
			if(dist[e.t]>c+e.c){
				dist[e.t]=c+e.c;
				que.push(P(c+e.c,e.t));
			}
		}
	}
}

//cruskal

bool comp(const log &e1,const log &e2){
	return e1.c>e2.c;
}

int init(int n){
	for(int i=0;i<n;i++)par[i]=i,rank[i]=0;
}

int find(int x){
	if(par[x]==x)return x;
	else (par[x]=find(par[x]));
}

bool same(int x,int y){
	return (find(y)==find(x));
}

void unite(int x,int y){
	x=find(x);
	y=find(y);
	
	if(x==y)return;
	if(rank[x]<rank[y])par[x]=y;
	else{
		par[y]=x;
		if(x==y)rank[x]++;
	}
}


void prim(){
	memset(used,false,sizeof(used));
	priority_queue<PP/*,vector<PP>,greater<PP>*/ > que;
	que.push(PP(0,P(0,-1)));
	while(que.size()){
		PP p=que.top();
		que.pop();
		int c=p.first,v=p.second.first,pv=p.second.second;
		if(used[v])continue;
		used[v]=true;
		if(pv!=-1){
			tree[v].push_back(edge(pv,c));
			tree[pv].push_back(edge(v,c));
		}
		for(int i=0;i<G[v].size();i++){
			edge e=G[v][i];
			if(!used[e.t]){
				que.push(PP(e.c,P(e.t,v)));
			}
		}
	}
}
//

int main(void){
	scanf("%d%d%d%d",&N,&M,&K,&Q);
	for(int i=0;i<M;i++){
		int a,b,c;
		log piece;
		scanf("%d%d%d",&a,&b,&c);
		a--,b--;
		G[a].push_back(edge(b,c));
		G[b].push_back(edge(a,c));
		piece.c=c;
		piece.f=a;
		piece.t=b;
		all.push_back(piece);
	}
	for(int i=0;i<K;i++){
		scanf("%d",&fest[i]);
		fest[i]--;
	}
	dijk();
	for(int i=0;i<N;i++){
		for(int j=0;j<G[i].size();j++){
			G[i][j].c=min(dist[i],dist[G[i][j].t]);
		}
	}
	/*
	sort(all.begin(),all.end(),comp);
	init(N);
	for(int i=0;i<all.size();i++){
		log p=all[i];
		printf("%d %d\n",find(p.f),find(p.t));
		if(!same(p.f,p.t)){
			unite(p.f,p.t);
			printf("f%d %d\n",find(p.f),find(p.t));
			tree[p.f].push_back(edge(p.t,p.c));
			tree[p.t].push_back(edge(p.f,p.c));
		}
	}
	*/
	prim();
	/*
	for(int i=0;i<N;i++){
		printf("%d ",i);
		for(int j=0;j<tree[i].size();j++)printf("%d ",tree[i][j].t);
		printf("\n");
	}*/
	rmg_init(N);
	for(int i=0;i<Q;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		a--,b--;
		printf("%d\n",query(a,b));
	}
	
	return 0;
}

Measured memory_bytes: 35440