#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
struct node {
  int bh, val;
  bool operator<(const node &b) const { return val > b.val; }
};
priority_queue<node> q;
int n, m, k, p;
int dis[N];
bool vis[N];
struct id {
  int next, to, w;
} a[M], e[M], e2[M];
int tot, tot2, head[N], head2[N];
int deep[N], fath[N][22], maxm[N][22];
bool cmp(id b, id c) { return b.w < c.w; }
int f[N];
int fa(int x) {
  if (f[x] != x) f[x] = fa(f[x]);
  return f[x];
}
void add(int from, int to, int w) {
  a[++tot].next = head[from];
  a[tot].to = to;
  a[tot].w = w;
  head[from] = tot;
}
void e2dd(int from, int to, int w) {
  e2[++tot2].next = head2[from];
  e2[tot2].to = to;
  e2[tot2].w = w;
  head2[from] = tot2;
}
void build() {
  for (int i = 1; i <= n; i++) f[i] = i;
  int cnt = 0;
  for (int i = 1; i <= m; i++) {
    int a = fa(e[i].next);
    int b = fa(e[i].to);
    if (a != b) {
      f[a] = b;
      e2dd(e[i].next, e[i].to, e[i].w);
      e2dd(e[i].to, e[i].next, e[i].w);
      cnt++;
      if (cnt == n - 1) return;
    }
  }
}
void dfs(int now, int up) {
  fath[now][0] = up;
  for (int i = head2[now]; i; i = e2[i].next) {
    int to = e2[i].to;
    if (to == up) continue;
    deep[to] = deep[now] + 1;
    maxm[to][0] = e2[i].w;
    dfs(to, now);
  }
}
int print(int x, int y) {
  int res = 0;
  if (deep[x] < deep[y]) swap(x, y);
  for (int i = 20; i >= 0; i--) {
    if (deep[fath[x][i]] < deep[y]) continue;
    res = max(res, maxm[x][i]);
    x = fath[x][i];
  }
  if (x == y) return res;
  for (int i = 20; i >= 0; i--) {
    if (fath[x][i] == fath[y][i]) continue;
    res = max(res, max(maxm[x][i], maxm[y][i]));
    x = fath[x][i];
    y = fath[y][i];
  }
  res = max(res, max(maxm[x][0], maxm[y][0]));
  return res;
}
void dij() {
  memset(dis, 0x3f3f3f3f, sizeof(dis));
  dis[0] = 0;
  q.push((node){0, 0});
  while (!q.empty()) {
    node u = q.top();
    q.pop();
    if (vis[u.bh]) continue;
    vis[u.bh] = true;
    for (int i = head[u.bh]; i; i = a[i].next) {
      int v = a[i].to;
      if (dis[v] > dis[u.bh] + a[i].w) {
        dis[v] = dis[u.bh] + a[i].w;
        if (!vis[v]) q.push((node){v, dis[v]});
      }
    }
  }
}
int main() {
  scanf("%d%d%d%d", &n, &m, &k, &p);
  for (int i = 1; i <= m; i++) {
    int from, to, w;
    scanf("%d%d%d", &from, &to, &w);
    add(from, to, w);
    add(to, from, w);
    e[i].next = from;
    e[i].to = to;
    e[i].w = w;
  }
  for (int i = 1; i <= k; i++) {
    add(0, i, 0);
    add(i, 0, 0);
  }
  dij();
  for (int i = 1; i <= m; i++) e[i].w += dis[e[i].next] + dis[e[i].to];
  sort(e + 1, e + m + 1, cmp);
  build();
  deep[1] = 1;
  dfs(1, -1);
  for (int i = 1; i <= 20; i++) {
    for (int j = 1; j <= n; j++) {
      fath[j][i] = fath[fath[j][i - 1]][i - 1];
      maxm[j][i] = max(maxm[j][j - 1], maxm[fath[j][i - 1]][i - 1]);
    }
  }
  for (int i = 1; i <= p; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    printf("%d\n", print(x, y));
  }
}
