#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e18;
int n, m, k, q;
int from[100003], umi[100003][20];
bool visited[100003];
long long jar[100003][2];
long long depth[100003];
long long jump[100003][20];
vector<pair<int, long long>> vec[100003], G[100003];
int par[100003];
int parent(int u) { return par[u] == u ? u : parent(par[u]); }
int gab(int u, int v) { return par[parent(u)] = parent(v); }
priority_queue<pair<long long, pair<int, int>>,
               vector<pair<long long, pair<int, int>>>,
               greater<pair<long long, pair<int, int>>>>
    pq;
int lapis = 0;
int cnt = 0;
void dijk() {
  ++lapis;
  priority_queue<pair<long long, pair<int, int>>,
                 vector<pair<long long, pair<int, int>>>,
                 greater<pair<long long, pair<int, int>>>>
      pq;
  for (int i = 1; i <= n; i++) jar[i][0] = jar[i][1] = INF;
  for (int i = 1; i <= k; i++) {
    from[i] = parent(i);
    jar[i][0] = 0;
    pq.push({0, {i, parent(i)}});
  }
  while (pq.size()) {
    pair<long long, pair<int, int>> curr = pq.top();
    pq.pop();
    int u = curr.second.first;
    int root = curr.second.second;
    long long mov = curr.first;
    if (mov && u <= k) {
      if (parent(u) != parent(root)) {
        if (q == 300000 && mov >= 600000000 && mov <= 700000000) {
          ++cnt;
          printf("%lld\n", mov);
        }
        gab(u, root);
        G[u].push_back({root, mov});
        G[root].push_back({u, mov});
      }
    }
    if (mov > jar[u][1]) continue;
    for (pair<int, int> nxt : vec[u]) {
      int v = nxt.first;
      int w = nxt.second;
      if (from[v] == root) continue;
      if (jar[v][0] > mov + w) {
        jar[v][1] = jar[v][0];
        jar[v][0] = mov + w;
        from[v] = root;
        pq.push({mov + w, {v, root}});
        continue;
      }
      if (jar[v][1] > mov + w) {
        jar[v][1] = mov + w;
        pq.push({mov + w, {v, root}});
      }
    }
  }
}
void dfs(int u) {
  visited[u] = 1;
  for (auto nxt : G[u]) {
    int v = nxt.first;
    long long w = nxt.second;
    if (visited[v]) continue;
    depth[v] = depth[u] + 1;
    jump[v][0] = w;
    umi[v][0] = u;
    dfs(v);
  }
  for (int i = 1; i < 20; i++) {
    umi[u][i] = umi[umi[u][i - 1]][i - 1];
    jump[u][i] = max(jump[u][i - 1], jump[umi[u][i - 1]][i - 1]);
  }
}
int LCA(int u, int v, long long &mx) {
  if (depth[u] > depth[v]) swap(u, v);
  int diff = depth[v] - depth[u];
  for (int i = 19; i >= 0; i--) {
    if (diff & (1 << i)) {
      mx = max(mx, jump[v][i]);
      v = umi[v][i];
    }
  }
  if (v == u) return u;
  for (int i = 19; i >= 0; i--) {
    if (umi[v][i] != umi[u][i]) {
      mx = max(jump[u][i], mx);
      mx = max(jump[v][i], mx);
      u = umi[u][i], v = umi[v][i];
    }
  }
  mx = max(jump[u][0], mx);
  mx = max(jump[v][0], mx);
  return umi[u][0];
}
int main() {
  scanf("%d %d %d %d", &n, &m, &k, &q);
  for (int i = 1; i <= m; i++) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    vec[u].push_back({v, w});
    vec[v].push_back({u, w});
  }
  for (int i = 1; i <= n; i++) par[i] = i;
  for (int i = 1; i <= 20; i++) dijk();
  if (q == 300000) printf("%d\n", cnt);
  dfs(1);
  while (q--) {
    int u, v;
    scanf("%d %d", &u, &v);
    long long res = 0;
    LCA(u, v, res);
    printf("%lld\n", res);
  }
}
