#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define MAX_V (100001)
#define MAX_LOG_V (18)
#define INF (1<<29)
#define F first
#define S second
typedef pair<int,int> P;
typedef pair<int,P> PP;
struct edge{
  int to,cost;
  edge(int to,int cost) : to(to),cost(cost) {}
};

struct uni{
  int U[MAX_V];
  uni(){}
  void init(){ memset(U,-1,sizeof(U)); }
  void set(int x,int y){
    x = root(x) , y = root(y);
    if( x != y ){
      if( U[y] < U[x] ) swap(x,y);
      U[x] += U[y]; U[y]=x;
    }
  }
  bool find(int x,int y){
    return root(x) == root(y);
  }
  int root(int x){
    return U[x] < 0 ? x:U[x] = root(U[x]);
  }
};

int N,M,K,Q;
vector<edge> G[MAX_V];
vector<int> F;

int H[MAX_V];//ダイクストラのメモるとこ
vector<PP> G2;//線路全部メモ

uni u;//ユニオンファインド木

int root;

int depth[MAX_V];//根からの深さ
int parent[MAX_LOG_V][MAX_V];//親を2^k辿って云々
int min_q[MAX_LOG_V][MAX_V];//親を2^kたどった場所までの最小値
int id[MAX_V];//各頂点がeに初めて登場するインデックス
int es[(MAX_V-1) *2];//辺のインデックス

//int rmq[MAX_V*2 - 1];

void dijk(){
  priority_queue<P,vector<P>,greater<P> > q;
  fill(H,H+N,INF);
  for(int i=0;i<(int)F.size();i++){
    q.push( P( 0, F[i] ) );
    H[F[i]]=0;
  }
  while(!q.empty()){
    P p = q.top(); q.pop();
    int id = p.S;
    //  printf("%d %d\n",p.F,p.S);
    for(int i=0;i<(int)G[id].size();i++){
      edge e = G[id][i];
      if( H[e.to] > e.cost + p.F ){
	H[e.to] = e.cost + p.F;
	q.push( P(e.cost+p.F,e.to) );
      }
    }
  }

  u.init();

  for(int i=0;i<N;i++){
    for(int j=0;j<(int)G[i].size();j++){
      G2.push_back(PP(min(H[G[i][j].to],H[i]),P(i,G[i][j].to)));
    }
    G[i].clear();
  }
  
  sort(G2.rbegin(),G2.rend());

  for(int i=0;i<(int)G2.size();i++){
    int id = G2[i].S.F, to = G2[i].S.S;
    if( !u.find( id, to ) ){
      //      printf("%d %d\n",id+1,to+1);
      u.set(id,to);
      G[id].push_back(edge(to,min(H[id],H[to])));
      G[to].push_back(edge(id,min(H[id],H[to])));
    }
  }

}


void dfs(int v,int p,int d) {
  parent[0][v] = p;
  if( p==-1 ) min_q[0][v] = H[v];
  else min_q[0][v] = min(H[v],H[p]);
  depth[v] = d;
  for(int i=0;i<(int)G[v].size();i++)
    if(G[v][i].to != p) dfs(G[v][i].to, v, d+1);
}

void init(){
  dijk();
  root = 0;
  dfs(root, -1, 0);
  for(int k = 0; k+1 < MAX_LOG_V; k++) {
    for(int v = 0; v < N; v++){
      if( parent[k][v] < 0 ){
	parent[k+1][v]=-1;
	//min_q[k+1][v]=min_q[k][v];
      } else {
	parent[k+1][v] = parent[k][parent[k][v]];
	min_q[k+1][v] = min(min_q[k][v],min_q[k][parent[k][v]]);
      }
    }
  }
}

int lca(int u,int v){
  int ret = INF;
  if( depth[u] > depth[v] ) swap(u,v);
  for(int k=0;k<MAX_LOG_V;k++){
    //    printf("%d %d %d\n",k,depth[v],depth[u]);      
    if( ( depth[v] - depth[u] ) >> k & 1 ) {
      //       printf("%d\n", min_q[k][v]);
       ret = min(min_q[k][v],ret);
       v = parent[k][v];
    }
  }
  //  printf("%d\n",u+1);
  //  printf("%d %d\n",ret,v+1);
  if( u==v ) return ret;
  //二分探索
  for(int k=MAX_LOG_V-1;k>-1;k--){
    if( parent[k][u] != parent[k][v] ) {
      ret = min(min(min_q[k][v],min_q[k][u]),ret);
      u = parent[k][u];
      v = parent[k][v];
    }
  }
  //  printf("%d\n",parent[0][u]);
  //  return parent[0][u];
  return min(min(min_q[0][u],min_q[0][v]),ret);
  //  return ret;
}

int main(){
  scanf("%d %d %d %d",&N,&M,&K,&Q);
  for(int i=0;i<M;i++){
    int a,b,l;
    scanf("%d %d %d",&a,&b,&l);
    a--;  b--;
    G[a].push_back(edge(b,l));
    G[b].push_back(edge(a,l));
  }
  for(int i=0;i<K;i++){
    int f;
    scanf("%d",&f);
    f--;
    F.push_back(f);
  }
  init();
  for(int i=0;i<Q;i++){
    int s,t;
    scanf("%d %d",&s,&t);
    s--; t--;
    if(s==t) printf("%d\n",H[s]);
    else printf("%d\n",lca(s,t));
  }
}

Measured memory_bytes: 29828