#include <bits/stdc++.h>
using namespace std;
int n, m, ver[600005], nxt[600005], edge[600005], head[600005], tot;
void add(int x, int y, int z) {
  ver[++tot] = y;
  edge[tot] = z;
  nxt[tot] = head[x];
  head[x] = tot;
}
int vis[100005], dis[100005];
priority_queue<pair<int, int> > q;
void init_map() {
  memset(ver, 0, sizeof(ver));
  memset(edge, 0, sizeof(edge));
  memset(nxt, 0, sizeof(nxt));
  memset(head, 0, sizeof(head));
  tot = 0;
}
void dijkstra(int k) {
  memset(dis, 0x7f, sizeof(dis));
  dis[k] = 0;
  q.push(make_pair(0, k));
  while (q.size()) {
    int x = q.top().second;
    q.pop();
    if (vis[x]) continue;
    vis[x] = 1;
    for (int i = head[x]; i; i = nxt[i]) {
      int y = ver[i], z = edge[i];
      if (dis[y] > dis[x] + z) {
        dis[y] = dis[x] + z;
        q.push(make_pair(-dis[y], y));
      }
    }
  }
}
int fa[100005];
struct kru {
  long long dis, from, to;
} e[100005];
bool cmp(kru x, kru y) { return x.dis < y.dis; }
int getf(int x) {
  if (fa[x] == x)
    return x;
  else
    return getf(fa[x]);
}
void kruskal() {
  int cnt = 0;
  for (int i = 1; i <= n; i++) fa[i] = i;
  for (int i = 1; i <= m; i++) {
    kru x = e[i];
    if (getf(x.from) != getf(x.to)) {
      fa[getf(x.from)] = fa[getf(x.to)];
      add(x.from, x.to, x.dis);
      add(x.to, x.from, x.dis);
      cnt++;
      if (cnt == n - 1) break;
    }
  }
}
int dep[600005], f[600005][25], maxx[600005][25];
void dfs(int u, int fa) {
  f[u][0] = fa;
  for (int i = head[u]; i; i = nxt[i]) {
    int v = ver[i], z = edge[i];
    if (v == fa) continue;
    dep[v] = dep[u] + 1;
    maxx[v][0] = z;
    dfs(v, u);
  }
}
void init() {
  for (int i = 1; i <= 20; i++) {
    for (int j = 1; j <= n; j++) {
      f[j][i] = f[f[j][i - 1]][i - 1];
      maxx[j][i] = max(maxx[j][i - 1], maxx[f[j][i - 1]][i - 1]);
    }
  }
}
int get_ans(int x, int y) {
  int ans = 0;
  if (dep[x] < dep[y]) swap(x, y);
  for (int i = 20; i >= 0; i--) {
    if (dep[f[x][i]] < dep[y]) continue;
    ans = max(ans, maxx[x][i]);
    x = f[x][i];
  }
  if (x == y) return ans;
  for (int i = 20; i >= 0; i--) {
    if (f[x][i] == f[y][i]) continue;
    ans = max(ans, max(maxx[x][i], maxx[y][i]));
    x = f[x][i];
    y = f[y][i];
  }
  ans = max(ans, max(maxx[x][0], maxx[y][0]));
  return ans;
}
int main() {
  int k, q, sum;
  scanf("%d%d%d%d", &n, &m, &k, &q);
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    add(x, y, z);
    add(y, x, z);
    e[i].from = x;
    e[i].to = y;
    e[i].dis = z;
  }
  for (int i = 1; i <= k; i++) {
    add(0, i, 0);
    add(i, 0, 0);
  }
  dijkstra(0);
  for (int i = 1; i <= m; i++) {
    e[i].dis += dis[e[i].from];
    e[i].dis += dis[e[i].to];
  }
  sort(e + 1, e + m + 1, cmp);
  init_map();
  kruskal();
  dep[1] = 1;
  dfs(1, -1);
  init();
  for (int i = 1; i <= q; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    printf("%d\n", get_ans(x, y));
  }
  return 0;
}
