#include<bits/stdc++.h>
using namespace std;
 
#define reps(i,j,n) for(int i = (j) ; i < (int)(n) ; ++i)    
#define rep(i,n) reps(i,0,n)  
#define each(it,c) for(__typeof (c).begin() it = (c).begin(); it != (c).end(); it++)    
typedef pair< int , int > Pi;  
typedef pair< int , Pi > Pii;
typedef long long int64;  
const int INF = 1 << 30;  
template<typename T1, typename T2> istream& operator>>(istream& is, pair<T1,T2>& a){ return is>>a.first>>a.second; }  
template<typename T1, typename T2> ostream& operator<<(ostream& os, pair<T1,T2>& a){ return os<<a.first<<" "<<a.second; }  
template<typename T> istream& operator>>(istream& is, vector< T >& vc){ rep(i,sz(vc)) is >> vc[i]; return is;}  
template<typename T> ostream& operator<<(ostream& os, vector< T >& vc){ rep(i,sz(vc)) os << vc[i] << endl; return os; }


struct edge{ int to, cost; };
typedef vector< vector< edge > > Graph;
int N, M, K, Q;
Graph info;
vector< int > min_cost;
priority_queue< Pi, vector< Pi >, greater< Pi > > que;

class DisjointSet{
private:
  vector<int> rank, p;
  void link(int x,int y){
    if(rank[x] > rank[y]){
      p[y] = x;
    }else{
      p[x] = y;
      if(rank[x] == rank[y]) rank[y]++;
    }
  }
public:
  DisjointSet(){}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
  }
  void makeSet(int x){
    p[x] = x, rank[x] = 0;
  }
  void Union(int x,int y){
    link(findSet(x),findSet(y));
  }
  int findSet(int x){
    return( x != p[x] ? p[x] = findSet(p[x]) : p[x]);
  }
};
struct edge2{
  int u, v, cost;
  bool operator<(const edge2& hoge)const{
    return cost < hoge.cost;
  }
};
typedef vector< edge2 > Edges;
Edges kruskal(Edges& edges, int V){
  Edges newedges;
  sort( edges.rbegin(), edges.rend());
  DisjointSet uf_tree(V);
  for(int i = 0; i < V; i++){
    uf_tree.makeSet(i);
  }
  int ret = 0;
  for(int i = 0; i < edges.size(); i++){
    edge2& e = edges[i];
    if(uf_tree.findSet(e.u) != uf_tree.findSet(e.v)){
      uf_tree.Union( e.u, e.v);
      newedges.push_back( (edge2){ e.u, e.v, e.cost});
      ret += e.cost;
    }
  }
  return newedges;
}

void Dijkstra(){
  while(!que.empty()){
    Pi p = que.top(); que.pop();
    if(p.first > min_cost[p.second]) continue;
    for(int i = 0; i < info[p.second].size(); i++){
      edge& e = info[p.second][i];
      if(min_cost[e.to] == -1 || p.first + e.cost < min_cost[e.to]){
        min_cost[e.to] = p.first + e.cost;
        que.push( Pi( min_cost[e.to], e.to));
      }
    }
  }
}
#define MAX_LOG_V 18
#define MAX_V 100000
int par[MAX_LOG_V][MAX_V + 1];
struct LCA{
  vector<edge> g[MAX_V + 1] ;
  int dep[MAX_V + 1];
  int V,root;
  //引数:ノード数,根のノード番号
  LCA(int a,int b):V(a),root(b){}
  void add_edge(int x, int y, int cost){
    g[x].push_back((edge){y, cost});
    g[y].push_back((edge){x, cost});
  }
  void dfs(int v,int p){
    par[0][v]=p;
    dep[v]=(p==-1?0:dep[p]+1);
    for(int i=0;i<g[v].size();i++){
      if(g[v][i].to != p) dfs(g[v][i].to,v);
    }
  }
  void init(){
    dfs(root,-1);
    for(int k=0;k<MAX_LOG_V-1;k++){
      for(int v=0;v<V;v++){
        if(par[k][v]<0)par[k+1][v]=-1;
        else par[k+1][v]=par[k][par[k][v]];
      }
    }
  }
  int build(int u,int v){
    if(dep[u]>dep[v])swap(u,v);
    int prevu = u, prevv = v;

    for(int k=0;k<MAX_LOG_V;k++){
      if((dep[v]-dep[u])>>k&1)v=par[k][v];
    }
    if(u!=v){
      for(int k=MAX_LOG_V-1;k>=0;k--){
        if(par[k][u]!=par[k][v]){
          u=par[k][u];
          v=par[k][v];
        }
      }
      u = par[0][u];
    }
    int ret = min( min_cost[prevv], min_cost[prevu]);
    while(prevu != u){
      prevu = par[0][prevu];
      ret = min( ret, min_cost[prevu]);
    }
    while(prevv != u){
      prevv = par[0][prevv];
      ret = min( ret, min_cost[prevv]);
    }
    return ret;
  }
};

int main(){

  cin >> N >> M >> K >> Q;
  info.resize(N);
  min_cost.resize(N, -1);

  Edges edges;
  for(int i = 0, a, b, l; i < M; i++){
    cin >> a >> b >> l;
    a--, b--;
    info[a].push_back( (edge){ b, l});
    info[b].push_back( (edge){ a, l});
    edges.push_back( (edge2){ a, b});
  }
  for(int i = 0, f; i < K; i++){
    cin >> f;
    que.push( Pi( 0, f - 1));
    min_cost[f - 1] = 0;
  }
  Dijkstra();
  for(int i = 0; i < M; i++){
    edges[i].cost = min( min_cost[edges[i].u], min_cost[edges[i].v]);
  }
  edges = kruskal(edges, N);
  LCA lca( N, 0);
  for(int i = 0; i < edges.size(); i++){
    lca.add_edge( edges[i].u, edges[i].v, edges[i].cost);
  }
  lca.init();
  while(Q--){
    int a, b;
    cin >> a >> b;
    cout << lca.build(a - 1,b - 1) << endl;
  }
}

Measured memory_bytes: 26300