#include <bits/stdc++.h>
#pragma optimization_level 3
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 3e5 + 9;
int n, m, q, k;
struct edge {
  long long f, t, w;
  bool operator<(const edge& ri) const { return w > ri.w; }
};
vector<edge> G[maxn];
vector<edge> H[maxn];
long long dis[maxn];
bool vis[maxn];
void dij(int n, int s) {
  fill(vis, vis + n + 4, 0);
  fill(dis, dis + n + 4, inf);
  dis[s] = 0;
  priority_queue<edge> Q;
  Q.push({-1, s, 0});
  while (Q.size()) {
    edge now = Q.top();
    Q.pop();
    long long& u = now.t;
    if (!vis[u]) {
      vis[u] = 1;
      for (edge& e : G[u]) {
        long long v = e.t, w = e.w;
        if (!vis[v] && dis[v] > dis[u] + w) {
          dis[v] = dis[u] + w;
          Q.push({-1, v, dis[v]});
        }
      }
    }
  }
}
int fa[maxn];
int ff(int x) { return x == fa[x] ? x : fa[x] = ff(fa[x]); }
bool unite(int x, int y) {
  x = ff(x);
  y = ff(y);
  if (x == y) return 0;
  fa[x] = y;
  return 1;
}
void rebuild() {
  for (int u = int(1); u <= int(n); ++u)
    for (auto e : G[u]) {
      H[0].push_back({e.f, e.t, e.w + dis[e.f] + dis[e.t]});
    }
  sort(H[0].begin(), H[0].end());
  reverse(H[0].begin(), H[0].end());
  for (int i = int(1); i <= int(n); ++i) fa[i] = i;
  for (auto e : H[0])
    if (e.t != n + 1 && e.f != n + 1) {
      if (unite(e.f, e.t))
        H[e.f].push_back({e.f, e.t, e.w}), H[e.t].push_back({e.t, e.f, e.w});
    }
}
const int logdep = 23;
int depth[maxn];
long long gpow[maxn][logdep], mapow[maxn][logdep];
void dfs(int u, int p, long long w, int dep) {
  depth[u] = dep;
  gpow[u][0] = p;
  mapow[u][0] = w;
  for (int j = 1; (1 << j) < depth[u]; ++j)
    gpow[u][j] = gpow[gpow[u][j - 1]][j - 1],
    mapow[u][j] = max(mapow[u][j - 1], mapow[gpow[u][j - 1]][j - 1]);
  for (auto e : H[u])
    if (e.t != p) dfs(e.t, u, e.w, dep + 1);
}
long long LCA2(int x, int y) {
  if (depth[x] < depth[y]) swap(x, y);
  long long ans(0);
  int cha = depth[x] - depth[y];
  for (int p = 0; cha; ++p)
    if (cha & (1 << p)) {
      ans = max(ans, mapow[x][p]);
      x = gpow[x][p];
      cha -= (1 << p);
    }
  if (x == y) return ans;
  for (int i = logdep - 1; i >= 0; --i) {
    if (gpow[x][i] != gpow[y][i]) {
      ans = max(ans, mapow[x][i]);
      ans = max(ans, mapow[y][i]);
      x = gpow[x][i];
      y = gpow[y][i];
    }
  }
  ans = max(ans, mapow[x][0]);
  ans = max(ans, mapow[y][0]);
  return ans;
}
int main() {
  ios::sync_with_stdio(0);
  cin >> n >> m >> k >> q;
  for (int i = int(1); i <= int(k); ++i) {
    int c = i;
    G[n + 1].push_back({n + 1, c, 0});
    G[c].push_back({c, n + 1, 0});
  }
  for (int i = int(1); i <= int(m); ++i) {
    int f, t, w;
    cin >> f >> t >> w;
    G[f].push_back({f, t, w});
    G[t].push_back({t, f, w});
  }
  dij(n + 1, n + 1);
  rebuild();
  dfs(1, 1, -1, 1);
  for (int i = int(1); i <= int(q); ++i) {
    int f, t;
    cin >> f >> t;
    cout << LCA2(f, t) << '\n';
  }
  return 0;
}
