#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6 + 6;
long long int n, m, k, q, dist[MAX], par[MAX], lvl[MAX];
vector<pair<long long int, pair<long long int, long long int> > > vec;
vector<pair<long long int, long long int> > edg[MAX];
long long int ptable[MAX][20], wtable[MAX][20];
void dijk() {
  for (int i = k + 1; i <= n; i++) dist[i] = 1e9;
  priority_queue<pair<long long int, long long int> > pq;
  for (int i = 1; i <= k; i++) pq.push({0, i});
  while (!pq.empty()) {
    long long int node = pq.top().second;
    long long int wt = -pq.top().first;
    pq.pop();
    if (wt != dist[node]) continue;
    for (auto x : edg[node]) {
      long long int xx = x.second;
      long long int ww = x.first;
      if (dist[xx] > ww + wt) {
        dist[xx] = ww + wt;
        pq.push({-dist[xx], xx});
      }
    }
  }
}
long long int boss(long long int x) {
  return (par[x] == x) ? x : (par[x] = boss(par[x]));
}
void dfs(int node, int p, int lev) {
  lvl[node] = lev;
  for (auto x : edg[node]) {
    if (x.second == p) continue;
    ptable[x.second][0] = node;
    wtable[x.second][0] = x.first;
    dfs(x.second, node, lev + 1);
  }
}
long long int query(int u, int v) {
  if (lvl[u] < lvl[v]) swap(u, v);
  long long int ret = 0;
  while (lvl[u] > lvl[v]) {
    int logval = log2(lvl[u] - lvl[v]);
    ret = max(ret, wtable[u][logval]);
    u = ptable[u][logval];
  }
  if (u == v) return ret;
  for (int logval = log2(lvl[u]); logval >= 0; logval--) {
    if (ptable[u][logval] != -1 && ptable[u][logval] != ptable[v][logval]) {
      ret = max(ret, wtable[u][logval]);
      ret = max(ret, wtable[v][logval]);
      u = ptable[u][logval];
      v = ptable[v][logval];
    }
  }
  return max(ret, max(wtable[u][0], wtable[v][0]));
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m >> k >> q;
  while (m--) {
    long long int u, v, w;
    cin >> u >> v >> w;
    edg[u].push_back({w, v});
    edg[v].push_back({w, u});
    vec.push_back({w, {u, v}});
  }
  dijk();
  for (auto &x : vec) {
    x.first += dist[x.second.second] + dist[x.second.first];
  }
  sort(vec.begin(), vec.end());
  for (int i = 1; i <= n; i++) par[i] = i;
  for (int i = 1; i <= n; i++) edg[i].clear();
  for (auto x : vec) {
    long long int wt = x.first;
    long long int u = x.second.first;
    long long int v = x.second.second;
    long long int parU = boss(u);
    long long int parV = boss(v);
    if (parU != parV) {
      par[parU] = parV;
      edg[u].push_back({wt, v});
      edg[v].push_back({wt, u});
    }
  }
  memset(ptable, -1, sizeof ptable);
  dfs(1, -1, 0);
  for (int j = 1; (1 << j) <= n; j++) {
    for (int i = 1; i <= n; i++) {
      if (ptable[i][j - 1] != -1) {
        ptable[i][j] = ptable[ptable[i][j - 1]][j - 1];
        wtable[i][j] = max(wtable[i][j - 1], wtable[ptable[i][j - 1]][j - 1]);
      }
    }
  }
  while (q--) {
    int u, v;
    cin >> u >> v;
    cout << query(u, v) << '\n';
  }
  return 0;
}
