#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

vector<pii> g[100000];
int N,M,K,Q;

int dist[200000];
int f[100000];

void dijkstra() {
  REP(i,N) dist[i] = INF;
  priority_queue<pii> Q;
  REP(i,K) {
    Q.push(pii(0,f[i]));
    dist[f[i]] = 0;
  }
  while(!Q.empty()) {
    pii p = Q.top(); Q.pop();
    int d = -p.first;
    int now = p.second;
    if (dist[now] < d) continue;
    FOR(it, g[now]) {
      int nd = d + it->second;
      if (dist[it->first] > nd) {
        dist[it->first] = nd;
        Q.push(pii(-nd, it->first));
      }
    }
  }
}

template <class T> 
struct UnionFind {
  vector<int> data;
  vector<T> val;
  UnionFind(int size) : data(size, -1), val(size) {
    REP(i,size) val[i] = i;
  }
  bool unionSet(int x, int y, T v) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
      val[x] = v;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
  T &value(int x) {
    return val[root(x)];
  }
};

typedef pair<int, pii> P;
P edges[200000];

vector<int> tree[200000];

void spanningTree() {
  REP(i,2*N) tree[i].clear();
  int num = 0;
  REP(i,N) FOR(it, g[i]) if (i<it->first)
    edges[num++] = (P(min(dist[i], dist[it->first]), pii(i,it->first)));
  assert(num == M);
  sort(edges, edges+num, greater<P>());

  UnionFind<int> uf(N);
  int cnt = N;
  REP(i,num) {
    int a = edges[i].second.first;
    int b = edges[i].second.second;
    if (!uf.findSet(a,b)) {
      int x = uf.value(a);
      int y = uf.value(b);
      uf.unionSet(a,b,cnt);
      tree[cnt].push_back(x);
      tree[cnt].push_back(y);
      tree[x].push_back(cnt);
      tree[y].push_back(cnt);
      dist[cnt] = edges[i].first;
      cnt++;
    }
  }
  assert(cnt == 2*N-1);
}


const int MAX_N = 400000*2;
pii dat[MAX_N * 2 - 1];
int rmq_n;
void rmq_init(int *v, int size) {
  for (rmq_n=1; rmq_n<size; rmq_n*=2);
  REP(i,2*rmq_n-1) dat[i]=pii(INF,-1);
  REP(i,size) {
    dat[rmq_n-1+i] = pii(v[i], i);
  }
  for (int i=rmq_n-2; i>=0; --i)
    dat[i] = min(dat[i*2+1], dat[i*2+2]);
}
pii query(int a, int b, int k, int l, int r) {
  if (r <= a || b <= l) return pii(INF,-1);
  if (a <= l && r <= b) return dat[k];
  return min(query(a, b, k*2+1, l, (l+r)/2),
             query(a, b, k*2+2, (l+r)/2, r));
}
int q(int a, int b) {
  return query(a, b, 0, 0, rmq_n).second;
}

const int MAX_V = 200000;

int vs[MAX_V*2-1];
int depth[MAX_V*2-1];
int id[MAX_V];

void dfs(int v, int p, int d, int &k) {
  id[v] = k;
  vs[k] = v;
  depth[k++] = d;
  FOR(it, tree[v]) {
    if (*it != p) {
      dfs(*it, v, d+1, k);
      vs[k] = v;
      depth[k++] = d;
    }
  }
}

void lca_init(int V, int root) {
  int k = 0;
  dfs(root, -1, 0, k);
  rmq_init(depth, V*2-1);
}

int lca(int u, int v) {
  if (id[u]>id[v]) swap(u,v);
  return vs[q(id[u],id[v]+1)];
}

int main() {
  ios::sync_with_stdio(0);
  while(cin>>N>>M>>K>>Q) {
    REP(i,N) g[i].clear();
    REP(i,M) {
      int a, b, c;
      cin >> a >> b >> c;
      a--; b--;
      g[a].push_back(pii(b,c));
      g[b].push_back(pii(a,c));
    }
    REP(i,K) {
      cin >> f[i];
      f[i]--;
    }
    dijkstra();
    spanningTree();
    // REP(i,2*N-1) {
    //   cout << i << " :";
    //   FOR(it, tree[i]) {
    //     cout << " " << *it;
    //   }
    //   cout << endl;
    // }
    lca_init(2*N-1, 2*N-2);
    REP(i,Q) {
      int a, b;
      cin >> a >> b;
      a--;b--;
      cout << dist[lca(a,b)] << endl;
    }
  }
}

Measured memory_bytes: 46280