#include <bits/stdc++.h>
using namespace std;
const int MaxN = 1e5 + 5, MaxM = 6e5 + 5, LOGN = 18;
struct node {
  int p, bel;
  long long dis;
  node(int a, int b, long long c) {
    p = a;
    bel = b;
    dis = c;
  }
  bool operator<(const node &A) const { return dis > A.dis; }
};
int n, m, k;
namespace Rebuild {
int logn, fa[MaxN][LOGN], dep[MaxN], fath[MaxN];
long long dis[MaxN][LOGN];
map<int, long long> MP[MaxN], MP2[MaxN];
void Add(int s, int e, long long w) {
  if ((MP[s].count(e) == 0) || (MP[s][e] > w)) MP[s][e] = w;
}
void Dfs(int s) {
  dep[s] = dep[fa[s][0]] + 1;
  for (int i = 1; i <= logn; i++) {
    fa[s][i] = fa[fa[s][i - 1]][i - 1];
    dis[s][i] = max(dis[s][i - 1], dis[fa[s][i - 1]][i - 1]);
  }
  int e;
  for (auto edge : MP2[s])
    if ((e = edge.first) != fa[s][0]) {
      fa[e][0] = s;
      dis[e][0] = edge.second;
      Dfs(e);
    }
}
int GetF(int x) { return (x == fath[x]) ? x : (fath[x] = GetF(fath[x])); }
void MST() {
  priority_queue<node> Q;
  for (int s = 1; s <= n; s++) fath[s] = s;
  for (int s = 1; s <= n; s++)
    for (auto it : MP[s]) Q.emplace(s, it.first, it.second);
  int cnt = n - 1;
  while (cnt) {
    node P = Q.top();
    Q.pop();
    int a = P.bel, b = P.p;
    int Fa = GetF(a), Fb = GetF(b);
    if (Fa != Fb) {
      cnt--;
      fath[Fa] = Fb;
      MP2[a][b] = MP2[b][a] = P.dis;
    }
  }
}
void Build() {
  for (logn = 1; (1 << logn) < n; logn++)
    ;
  MST();
  Dfs(1);
}
void LCA(int s, int e) {
  if (dep[s] < dep[e]) swap(s, e);
  int delta = dep[s] - dep[e];
  long long res = 0;
  for (int i = 0; delta; i++)
    if (delta & (1 << i)) {
      delta ^= (1 << i);
      res = max(res, dis[s][i]);
      s = fa[s][i];
    }
  if (s != e) {
    for (int i = logn; i >= 0; i--)
      if (fa[s][i] != fa[e][e]) {
        res = max(res, max(dis[s][i], dis[e][i]));
        s = fa[s][i];
        e = fa[e][i];
      }
    res = max(res, max(dis[s][0], dis[e][0]));
  }
  cout << res << "\n";
}
}  // namespace Rebuild
namespace init {
priority_queue<node> Q;
int all = 0, star[MaxN], nxt[MaxM], ent[MaxM], Bel[MaxN];
long long len[MaxM], dis[MaxN];
void Add(int s, int e, long long w) {
  nxt[++all] = star[s];
  star[s] = all;
  ent[all] = e;
  len[all] = w;
}
void DIJ() {
  for (int s = 1; s <= k; s++) {
    Bel[s] = s;
    for (int edge = star[s]; edge; edge = nxt[edge])
      Q.emplace(ent[edge], s, len[edge]);
  }
  int s, e, bels;
  long long ndis;
  while (!Q.empty()) {
    node P = Q.top();
    Q.pop();
    s = P.p;
    if (Bel[s]) continue;
    dis[s] = ndis = P.dis;
    Bel[s] = bels = P.bel;
    for (int edge = star[s]; edge; edge = nxt[edge]) {
      e = ent[edge];
      if (Bel[e]) continue;
      Q.emplace(e, bels, ndis + len[edge]);
    }
  }
}
void init() {
  int s, e;
  long long w;
  for (int i = 1; i <= m; i++) {
    cin >> s >> e >> w;
    Add(s, e, w);
    Add(e, s, w);
  }
  DIJ();
  for (int s = k + 1; s <= n; s++) Rebuild::Add(s, Bel[s], dis[s]);
  for (int s = 1; s <= n; s++) {
    int e;
    for (int edge = star[s]; edge; edge = nxt[edge]) {
      e = ent[edge];
      if ((s < e) && (Bel[s] != Bel[e]))
        Rebuild::Add(Bel[s], Bel[e], len[edge] + dis[s] + dis[e]);
    }
  }
}
}  // namespace init
int main() {
  cin.tie(nullptr);
  cout.tie(nullptr);
  int q, s, e;
  cin >> n >> m >> k >> q;
  init::init();
  Rebuild::Build();
  while (q--) {
    cin >> s >> e;
    Rebuild::LCA(s, e);
  }
}
