#include <bits/stdc++.h>
using namespace std;
namespace fio {
streambuf* in = cin.rdbuf();
char bb[1000000], *s = bb, *t = bb;
inline int read() {
  int x = 0;
  char ch =
      (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF : *s++);
  while (ch < 48)
    ch = (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF
                                                                    : *s++);
  while (ch >= 48)
    x = x * 10 + ch - 48,
    ch = (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF
                                                                    : *s++);
  return x;
}
}  // namespace fio
using fio::read;
using mp = pair<int, long long>;
using mt = tuple<int, int, long long>;
int n, k, m, q;
int fa[100005], siz[100005], dep[100005];
long long dis[100005];
int find(int x) { return x == fa[x] ? x : find(fa[x]); }
vector<mp> road[100005];
int col[100005];
long long ds[100005];
class comp {
 public:
  bool operator()(mt x, mt y) { return get<2>(x) > get<2>(y); }
};
priority_queue<mt, vector<mt>, comp> huaji;
int gdep(int x) {
  return dep[x] ? dep[x] : (x == fa[x] ? dep[x] = 1 : dep[x] = gdep(fa[x]) + 1);
}
long long query(int x, int y) {
  long long ans = 0;
  if (dep[x] < dep[y]) swap(x, y);
  while (dep[x] > dep[y]) ans = max(ans, dis[x]), x = fa[x];
  while (x != y) ans = max(ans, max(dis[x], dis[y])), x = fa[x], y = fa[y];
  return ans;
}
inline void link(int x, int y, long long dis) {
  if (x == y) return;
  if (siz[x] < siz[y]) swap(x, y);
  siz[x] += siz[y], fa[y] = x, ::dis[y] = dis;
}
int main() {
  n = read(), m = read(), k = read(), q = read();
  for (int i = 1; i <= k; i++) fa[i] = i, siz[i] = 1;
  for (int i = 1, x, y, z; i <= m; i++)
    road[x = read()].push_back({y = read(), z = read()}),
        road[y].emplace_back(x, z);
  memset(ds, 0x3f, sizeof(ds));
  for (int i = 1; i <= k; i++) huaji.push({i, i, 0}), ds[i] = 0;
  while (huaji.size()) {
    mt wt = huaji.top();
    huaji.pop();
    int x = get<0>(wt), cc = get<1>(wt);
    long long len = get<2>(wt);
    if (col[x] && col[x] != cc) link(find(col[x]), find(cc), ds[x] + len);
    if (ds[x] < len || col[x]) continue;
    col[x] = cc;
    for (mp it : road[x]) {
      if (ds[get<0>(it)] > len + get<1>(it)) ds[get<0>(it)] = len + get<1>(it);
      col[get<0>(it)] ? void() : huaji.push({get<0>(it), cc, len + get<1>(it)});
    }
  }
  for (int i = 1; i <= k; i++) gdep(i);
  for (int i = 1; i <= q; i++) printf("%lld\n", query(read(), read()));
}
