#include <bits/stdc++.h>
using namespace std;
struct T {
  long long u, v, w;
} A[300005];
struct TT {
  long long u, v, w;
  bool operator<(const TT &b) const { return w > b.w; }
};
vector<T> Adj[100005], nAdj[200005];
priority_queue<TT> PQ;
bool cmp(T a, T b) { return a.w < b.w; }
long long N[100005], D[200005], P[200005], W[200005], L[200005][20],
    R[200005][20];
void findNearestCentral() {
  TT pNode, node;
  long long i, k, u, v;
  while (!PQ.empty()) {
    pNode = PQ.top();
    PQ.pop();
    if (N[pNode.v] != -1) {
      continue;
    }
    N[pNode.v] = pNode.u;
    D[pNode.v] = pNode.w;
    k = Adj[pNode.v].size();
    for (i = 0; i < k; i++) {
      v = Adj[pNode.v][i].v;
      node.u = pNode.u;
      node.v = v;
      node.w = pNode.w + Adj[pNode.v][i].w;
      PQ.push(node);
    }
  }
}
long long Max(long long a, long long b) { return a > b ? a : b; }
long long parent(long long u) {
  if (P[u] == u) {
    return u;
  }
  return P[u] = parent(P[u]);
}
void dfs(long long u, long long d) {
  long long i, k = nAdj[u].size();
  D[u] = d;
  for (i = 0; i < k; i++) {
    if (D[nAdj[u][i].v] == -1) {
      dfs(nAdj[u][i].v, d + 1);
      P[nAdj[u][i].v] = u;
    }
  }
}
int main() {
  long long n, m, kk, q, i, j, k, l, u, v, w;
  scanf("%lld%lld%lld%lld", &n, &m, &kk, &q);
  T node;
  for (i = 0; i < m; i++) {
    scanf("%lld%lld%lld", &u, &v, &w);
    node.v = v;
    node.w = w;
    Adj[u].push_back(node);
    node.v = u;
    Adj[v].push_back(node);
  }
  TT pNode;
  for (i = 1; i <= kk; i++) {
    pNode.u = i;
    pNode.v = i;
    pNode.w = 0;
    PQ.push(pNode);
  }
  memset(N, -1, sizeof(N));
  findNearestCentral();
  l = 0;
  for (i = 1; i <= n; i++) {
    k = Adj[i].size();
    P[i] = i;
    for (j = 0; j < k; j++) {
      if (N[i] != N[Adj[i][j].v]) {
        A[l].u = N[i];
        A[l].v = N[Adj[i][j].v];
        A[l++].w = D[i] + D[Adj[i][j].v] + Adj[i][j].w;
      }
    }
  }
  sort(A, A + l, cmp);
  memset(W, 0, sizeof(W));
  for (i = 0; i < l; i++) {
    u = parent(A[i].u);
    v = parent(A[i].v);
    if (u != v) {
      node.v = ++kk;
      nAdj[u].push_back(node);
      node.v = u;
      nAdj[kk].push_back(node);
      node.v = kk;
      nAdj[v].push_back(node);
      node.v = v;
      nAdj[kk].push_back(node);
      P[u] = v;
      W[kk] = A[i].w;
    }
  }
  memset(D, -1, sizeof(D));
  memset(P, -1, sizeof(P));
  dfs(1, 0);
  memset(L, -1, sizeof(L));
  P[1] = 1;
  for (i = 1; i <= kk; i++) {
    L[i][0] = P[i];
    R[i][0] = Max(W[i], W[P[i]]);
  }
  for (i = 1; i <= 18; i++) {
    for (j = 1; j <= kk; j++) {
      if (L[j][i - 1] != -1) {
        R[j][i] = Max(R[j][i - 1], R[L[j][i - 1]][i - 1]);
        L[j][i] = L[L[j][i - 1]][i - 1];
      }
    }
  }
  while (q--) {
    scanf("%lld%lld", &u, &v);
    if (D[u] < D[v]) {
      u ^= v ^= u ^= v;
    }
    w = Max(W[u], W[v]);
    for (i = 18; i >= 0; i--) {
      if ((D[u] - (1 << i)) >= D[v]) {
        w = Max(w, R[u][i]);
        u = L[u][i];
      }
    }
    if (u != v) {
      for (i = 1; 1 << i <= D[u]; i++)
        ;
      for (i--; i >= 0; i--) {
        if (L[u][i] != -1 && u != v) {
          w = Max(w, Max(R[u][i], R[v][i]));
          u = L[u][i];
          v = L[v][i];
        }
      }
    }
    printf("%lld\n", w);
  }
  return 0;
}
