#include <iostream>
#include <vector>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define N (100000)
#define INF (1<<29)
int uf[N];
 
int find(int x){
        if(uf[x] == x) return x;
        else return uf[x] = find(uf[x]);
}
int unite(int x,int y){
        x = find(x) , y = find(y);
        if( rand() & 1 ) uf[x] = y;
        else uf[y] = x;
}
 
struct NODE{
        int from,to,cost;
        NODE(int from,int to,int cost) : from(from) , to(to) , cost(cost) {}
        NODE(int from,int to) : from(from) , to(to) , cost(-1) {}
        NODE(){}
        
};
 
int n,m,K,Q;    
 
int vCost[N];
vector<NODE> edges , eList[N] ;
vector<int> tree[N];
 
bool operator < (const NODE &a,const NODE &b){
        return a.cost > b.cost;
}
int dijkstra(){
        CLR(vCost,-1);
        priority_queue<NODE> Q;
        for(int i = 0 ; i < K ; i++){
                int a;
                scanf("%d",&a);
                --a;
                Q.push(NODE(-1,a,0));
        }
        while(Q.size()){
                NODE q = Q.top(); Q.pop();
                if(vCost[q.to] == -1) vCost[q.to] = q.cost;
                else continue;
                for(int i = 0 ; i < eList[q.to].size() ; ++i)
                        if(vCost[eList[q.to][i].to] == -1) Q.push(NODE(-1,eList[q.to][i].to,q.cost+eList[q.to][i].cost));
        }
}
 
int depth[N] , height[N] , number[N] , parent[N];
 
vector< vector<int> > ele , seg;
vector<int> next;
 
int doLH(int pos,int num){
        if(pos == -1) return 0;
 
        if(number[pos] != -1){
                next[num]=pos;
                return 0;
        }else{
                ele[num].push_back(pos);
                number[pos] = num;
                return height[pos] = doLH(parent[pos],num)+1;
        }
}
 
int genLH(int pos,int prev,int dep){
        parent[pos] = prev;
        depth[pos] = dep;
        for(int i = 0 ; i < tree[pos].size() ; ++i)
                if(tree[pos][i] != prev) genLH(tree[pos][i],pos,dep+1);

        return 0;
}
 
int RMQ_add(vector<int> &s,int x,int a){
        x += s.size()/2-1;
        while(x){ s[x] = min(s[x],a); x /= 2; }
}
 
int RMQ_get(vector<int> &s,int l,int r,int k,int a,int b){
        if(l > b || r < a) return INF;
        if(l <= a && b <= r) return s[k];
        int m = (a+b)/2;
        return min(RMQ_get(s,l,r,k*2,a,m),RMQ_get(s,l,r,k*2+1,m+1,b));
}
 
int parentMemo[20][N];
 
int genLCA(){
        for(int i = 0 ; i < n ; i++)
                parentMemo[0][i] = parent[i];
        for(int i = 1 ; i < 20 ; i++)
                for(int j = 0 ; j < n ; j++)
                        parentMemo[i][j] = parentMemo[i-1][j] != -1 ? parentMemo[i-1][parentMemo[i-1][j]] : -1 ;
}
 
int getLCA(int x,int y){
        int diff = abs(depth[x]-depth[y]);
		if(depth[x] < depth[y]) swap(x,y);
        for(int i = 0 ; i < 20 ; i++) if(diff>>i&1) x = parentMemo[i][x];
        if(x==y) return x;
        for(int i = 19 ; i >= 0 ; --i){
                if(parentMemo[i][x] != parentMemo[i][y]) x = parentMemo[i][x] , y = parentMemo[i][y];
        }
        return parent[x];
}
 
int genSegtree(){
        for(int i = 0 ; i < ele.size() ; i++){
				int bpow = 1;
				while(bpow < ele[i].size()*2) bpow *= 2;
				seg.push_back(vector<int>(bpow,INF));
                for(int j = 0 ; j < ele[i].size() ; j++){
					RMQ_add(seg.back(),height[ele[i][j]],vCost[ele[i][j]]);
				}
        }
}
 
int QQQ = 0;
int getSegtree(int from,int to){
	QQQ += seg[number[from]].size();
	if(number[from] == number[to]){
			if(height[from] < height[to])swap(height[from],height[to]);
			return RMQ_get(seg[number[from]],height[to],height[from],1,1,seg[number[from]].size()/2);
	}else{
			return min(
					getSegtree(next[number[from]],to) , 
					RMQ_get(seg[number[from]],1,height[from],1,1,seg[number[from]].size()/2)
			);
	}
}
 
int idx[100000];
bool cmp(const int &a,const int &b){
	return depth[a] > depth[b];
}
int main(){
		srand(time(NULL));
        scanf("%d%d%d%d",&n,&m,&K,&Q);
        for(int i = 0 ; i < m ; i++){
                int a,b,c;
				scanf("%d%d%d",&a,&b,&c);
                --a,--b;
                eList[a].push_back(NODE(a,b,c));
                eList[b].push_back(NODE(b,a,c));
                edges.push_back(NODE(a,b));
        }
        dijkstra();
        for(int i = 0 ; i < m ; i++)
                edges[i].cost = min(vCost[edges[i].from],vCost[edges[i].to]);
        sort(edges.begin(),edges.end());
        for(int i = 0 ; i < n ; i++)
                uf[i] = i;
        for(int i = 0 ; i < m ; i++){
			int x = edges[i].from , y = edges[i].to;
			if(find(x) != find(y)){
					unite(x,y);
					tree[y].push_back(x);
					tree[x].push_back(y);
			}
        }
		CLR(parent,-1);
        CLR(height,-1);
        CLR(number,-1);
                
        genLH(0,-1,0);
		for(int i = 0 ; i < n ; i++) idx[i] = i;
		sort(idx,idx+n,cmp);
        for(int pos = 0 ; pos < n ; pos++){
			
			if(number[idx[pos]] == -1){
					ele.push_back(vector<int>());
					next.push_back(-1);
					doLH(idx[pos],ele.size()-1);
			}
		}
        genLCA();
        genSegtree();
        for(int i = 0 ; i < Q ; i++){
                int s,t;
                scanf("%d%d",&s,&t);
				s--,t--;
                int p = getLCA(s,t);
                printf("%d\n",min(getSegtree(s,p),getSegtree(t,p)));
        }
         return 0;
}

Measured memory_bytes: 28000