#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, w = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') w = -1;
    c = getchar();
  }
  while (c <= '9' && c >= '0') {
    x = (x << 1) + (x << 3) + c - '0';
    c = getchar();
  }
  return w == 1 ? x : -x;
}
long long n, m, k, q, uu[600005], vv[600005], ww[600005], fr[600005], cnt,
    f[600005];
struct node {
  long long to, w;
};
struct node2 {
  long long v, w;
};
struct node3 {
  long long fr, to, w;
};
node3 a[600005];
vector<node> mp[600005], mp2[600005];
long long dis[600005];
bool vis[600005], vis2[600005];
inline bool operator<(node2 a, node2 b) { return a.w > b.w; }
inline bool cmp(node3 a, node3 b) { return a.w < b.w; }
priority_queue<node2> que;
long long dep[600005], fa[600005][25], fa2[600005][25];
inline void dij() {
  for (int i = 1; i <= k; i++) que.push((node2){i, 0});
  while (!que.empty()) {
    node2 u = que.top();
    que.pop();
    if (vis[u.v]) continue;
    for (int i = 0; i < mp[u.v].size(); i++) {
      node v = mp[u.v][i];
      if (dis[v.to] > dis[u.v] + v.w) {
        dis[v.to] = dis[u.v] + v.w;
        fr[v.to] = fr[u.v];
        que.push((node2){v.to, dis[v.to]});
      }
    }
  }
}
inline int getf(int x) {
  if (f[x] == x) return x;
  return f[x] = getf(f[x]);
}
inline void dfs(int u) {
  vis2[u] = 1;
  for (int i = 0; i < mp2[u].size(); i++) {
    node v = mp2[u][i];
    if (vis2[v.to] == 1) continue;
    fa[v.to][0] = u;
    fa2[v.to][0] = v.w;
    dep[v.to] = dep[u] + 1;
    dfs(v.to);
  }
}
inline long long sol(int x, int y) {
  long long tmp = 0;
  if (dep[x] < dep[y]) swap(x, y);
  while (dep[x] != dep[y]) tmp = max(tmp, fa2[x][0]), x = fa[x][0];
  while (x != y) {
    tmp = max(tmp, fa[x][0]);
    tmp = max(tmp, fa[y][0]);
    x = fa[x][0];
    y = fa[y][0];
  }
  return tmp;
}
int main() {
  n = read();
  m = read();
  k = read();
  q = read();
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read(), w = read();
    uu[i] = u;
    vv[i] = v;
    ww[i] = w;
    mp[u].push_back((node){v, w});
    mp[v].push_back((node){u, w});
  }
  for (int i = 1; i <= n; i++) dis[i] = 1e18;
  for (int i = 1; i <= k; i++) fr[i] = i, dis[i] = 0;
  dij();
  for (int i = 1; i <= m; i++) {
    if (fr[uu[i]] == fr[vv[i]]) continue;
    a[++cnt] = (node3){fr[uu[i]], fr[vv[i]], dis[uu[i]] + dis[vv[i]] + ww[i]};
  }
  sort(a + 1, a + cnt + 1, cmp);
  for (int i = 1; i <= n; i++) f[i] = i;
  for (int i = 1; i <= cnt; i++) {
    node3 tmp = a[i];
    int fu = getf(tmp.fr), fv = getf(tmp.to);
    if (fu == fv) continue;
    f[fu] = fv;
    mp2[fu].push_back((node){fv, tmp.w});
    mp2[fv].push_back((node){fu, tmp.w});
  }
  dfs(1);
  while (q--) {
    int x = read(), y = read();
    printf("%lld\n", sol(x, y));
  }
  return 0;
}
