#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int> > DSK[100005], G[100005];
int n, m, k;
long long Len[100005];
struct edge {
  int u, v;
  long long c;
};
vector<edge> edges;
void dijktra(int s) {
  Len[s] = 0;
  priority_queue<pair<int, int>, vector<pair<int, int> >,
                 greater<pair<int, int> > >
      Q;
  Q.push({0, s});
  set<int> S;
  while (!Q.empty()) {
    int u = Q.top().second;
    Q.pop();
    if (u != s && u <= k) {
      S.insert(u);
      continue;
    }
    for (pair<int, int> v : DSK[u])
      if (Len[v.first] > Len[u] + v.second) {
        Len[v.first] = Len[u] + v.second;
        Q.push({Len[v.first], v.first});
      }
  }
  for (auto u : S) edges.push_back({s, u, Len[u]});
}
int parent[100005];
int Find_Set(int u) {
  while (parent[u] > 0) u = parent[u];
  return u;
}
void Union(int u, int v) {
  int x = parent[u] + parent[v];
  if (parent[u] > parent[v]) {
    parent[v] = x;
    parent[u] = v;
  } else {
    parent[u] = x;
    parent[v] = u;
  }
}
int R[100005][50], h[100005];
long long val[100005][50];
void DFS(int u, int pre) {
  for (pair<int, int> v : G[u])
    if (v.first != pre) {
      h[v.first] = h[u] + 1;
      val[v.first][0] = v.second;
      R[v.first][0] = u;
      DFS(v.first, u);
    }
}
long long lca(int u, int v) {
  long long res = 0;
  if (h[u] < h[v]) swap(u, v);
  for (int i = log2(h[u]); i >= 0; i--)
    if (h[u] - (1 << i) >= h[v]) {
      res = max(res, val[u][i]);
      u = R[u][i];
    }
  if (u == v) return res;
  for (int i = log2(h[u]); i >= 0; i--)
    if (R[u][i] != 0 && R[u][i] != R[v][i]) {
      res = max(res, max(val[u][i], val[v][i]));
      u = R[u][i];
      v = R[v][i];
    }
  res = max(res, max(val[u][0], val[v][0]));
  return res;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int q;
  cin >> n >> m >> k >> q;
  for (int i = 1; i <= m; i++) {
    int u, v, c;
    cin >> u >> v >> c;
    DSK[u].push_back(make_pair(v, c));
    DSK[v].push_back(make_pair(u, c));
  }
  for (int i = 1; i <= n; i++) Len[i] = 1000000000000000;
  for (int i = 1; i <= k; i++) dijktra(i);
  sort(edges.begin(), edges.end(),
       [](const edge &A, const edge &B) { return A.c < B.c; });
  for (int i = 1; i <= n; i++) parent[i] = -1;
  for (edge e : edges) {
    int U = Find_Set(e.u);
    int V = Find_Set(e.v);
    if (U != V) {
      Union(U, V);
      G[e.u].push_back({e.v, e.c});
      G[e.v].push_back({e.u, e.c});
    }
  }
  DFS(1, 0);
  for (int j = 1; j <= log2(n); j++)
    for (int i = 1; i <= n; i++) {
      R[i][j] = R[R[i][j - 1]][j - 1];
      val[i][j] = max(val[i][j - 1], val[R[i][j - 1]][j - 1]);
    }
  while (q--) {
    int a, b;
    cin >> a >> b;
    cout << lca(a, b) << '\n';
  }
}
