#include <bits/stdc++.h>
using namespace std;
int X[1000005], Y[1000005];
long long Z[1000005];
struct side {
  int x, y;
  long long z;
} a[1000005];
int head[100005];
int cnt = 0;
void add(int x, int y, long long z) {
  a[++cnt].x = y;
  a[cnt].y = head[x];
  head[x] = cnt;
  a[cnt].z = z;
}
struct side2 {
  int x, y;
  long long z;
} A[1000005];
long long dis[100005];
struct node {
  int x;
  long long dis;
  bool operator<(const node &X) const { return X.dis < dis; }
};
priority_queue<node> q;
void dij() {
  q.push((node){0, 0ll});
  while (!q.empty()) {
    int x = q.top().x;
    q.pop();
    for (int i = head[x]; i; i = a[i].y) {
      int y = a[i].x;
      if (dis[x] + a[i].z < dis[y]) {
        dis[y] = dis[x] + a[i].z;
        q.push((node){y, dis[y]});
      }
    }
  }
}
bool cmp(side2 X, side2 Y) { return X.z < Y.z; }
int f[100005];
int fa(int x) { return (x == f[x]) ? x : f[x] = fa(f[x]); }
int F[100005][25];
long long maxn[100005][25];
bool vis[100005];
int dep[100005];
queue<int> qu;
void build() {
  qu.push(1);
  while (!qu.empty()) {
    int x = qu.front();
    qu.pop();
    for (int i = head[x]; i; i = a[i].y) {
      int y = a[i].x;
      if (!vis[y]) {
        qu.push(y);
        vis[y] = 1;
        F[y][0] = x;
        maxn[y][0] = a[i].z;
        dep[y] = dep[x] + 1;
      }
    }
  }
}
long long lca(int x, int y) {
  long long ans = 0ll;
  for (int i = 20; i >= 0; i--) {
    if (dep[F[x][i]] >= dep[y]) {
      ans = max(ans, maxn[x][i]);
      x = F[x][i];
    }
  }
  for (int i = 20; i >= 0; i--) {
    if (F[x][i] != F[y][i]) {
      x = F[x][i];
      y = F[y][i];
      ans = max(ans, max(maxn[x][i], maxn[y][i]));
    }
  }
  if (x != y) {
    ans = max(ans, max(maxn[x][0], maxn[y][0]));
  }
  return ans;
}
int main() {
  int n, m, k, q;
  scanf("%d%d%d%d", &n, &m, &k, &q);
  memset(dis, 0x3f, sizeof(dis));
  dis[0] = 0;
  for (int i = 1; i <= k; i++) add(0, i, 0ll), add(i, 0, 0ll);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%lld", &X[i], &Y[i], &Z[i]);
    add(X[i], Y[i], Z[i]);
    add(Y[i], X[i], Z[i]);
  }
  dij();
  for (int i = 1; i <= m; i++) A[i] = (side2){X[i], Y[i], Z[i]};
  sort(A + 1, A + m + 1, cmp);
  memset(a, 0, sizeof(a));
  memset(head, 0, sizeof(head));
  cnt = 0;
  for (int i = 1; i <= n; i++) f[i] = i;
  for (int i = 1; i <= m; i++) {
    int x = A[i].x, y = A[i].y;
    int fx = fa(x), fy = fa(y);
    if (fx != fy) {
      f[fy] = fx;
      add(x, y, dis[x] + dis[y] + A[i].z);
      add(y, x, dis[x] + dis[y] + A[i].z);
    }
  }
  vis[1] = 1;
  build();
  for (int j = 1; j <= 20; j++) {
    for (int i = 1; i <= n; i++) {
      F[i][j] = F[F[i][j - 1]][j - 1];
      maxn[i][j] = max(maxn[i][j - 1], maxn[F[i][j - 1]][j - 1]);
    }
  }
  for (int i = 1; i <= q; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    if (dep[x] < dep[y]) swap(x, y);
    long long ans = lca(x, y);
    printf("%lld\n", ans);
  }
  return 0;
}
