#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
namespace DSU {
int p[N];
int s[N];
int init(int n) {
  iota(p + 1, p + 1 + n, 1);
  fill(s + 1, s + 1 + n, 1);
  return 1;
}
int lead(int x) { return p[x] == x ? x : p[x] = lead(p[x]); }
int join(int x, int y) {
  x = lead(x);
  y = lead(y);
  if (x == y) return 0;
  p[y] = x;
  s[x] += s[y];
  return 1;
}
};  // namespace DSU
namespace Tree {
vector<pair<int, long long> > a[N];
long long M[N][20];
int p[N][20];
int h[N];
void addEdge(int u, int v, long long w) {
  a[u].emplace_back(v, w);
  a[v].emplace_back(u, w);
}
void dfs(int u, int P) {
  for (int i = 0; i < 16; ++i)
    p[u][i + 1] = p[p[u][i]][i], M[u][i + 1] = max(M[u][i], M[p[u][i]][i]);
  for (pair<int, long long> e : a[u])
    if (e.first != P) {
      h[e.first] = h[u] + 1;
      p[e.first][0] = u;
      M[e.first][0] = e.second;
      dfs(e.first, u);
    }
}
long long get(int u, int v) {
  long long res = 0;
  if (h[u] < h[v]) swap(u, v);
  int m = h[u] - h[v];
  for (int i = 0; i < 17; ++i)
    if (m >> i & 1) res = max(res, M[u][i]), u = p[u][i];
  if (u == v) return res;
  for (int i = 16; i >= 0; --i)
    if (p[u][i] != p[v][i]) {
      res = max(res, M[u][i]);
      u = p[u][i];
      res = max(res, M[v][i]);
      v = p[v][i];
    }
  return max(max(M[u][0], M[v][0]), res);
}
};  // namespace Tree
vector<pair<int, long long> > g[N];
long long d[N];
int p[N];
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m;
  cin >> n >> m;
  int k, q;
  cin >> k >> q;
  for (int i = 0; i < m; ++i) {
    int x;
    cin >> x;
    int y;
    cin >> y;
    int w;
    cin >> w;
    g[x].emplace_back(y, w);
    g[y].emplace_back(x, w);
  }
  fill(d + 1, d + 1 + n, 1e18);
  vector<tuple<long long, int, int> > candidate;
  priority_queue<pair<int, long long>, vector<pair<int, long long> >,
                 greater<pair<int, long long> > >
      pq;
  for (int i = 1; i <= k; ++i) {
    d[i] = 0;
    p[i] = i;
    pq.push(pair<int, long long>(0, i));
  }
  while (pq.size()) {
    long long du = pq.top().first;
    int u = pq.top().second;
    pq.pop();
    if (d[u] != du) continue;
    for (pair<int, long long> e : g[u]) {
      int v = e.first;
      long long w = e.second;
      if (p[v]) candidate.emplace_back(d[u] + w + d[v], p[v], p[u]);
      if (d[v] > du + w) {
        d[v] = du + w;
        p[v] = u;
        pq.push(pair<int, long long>(d[v], v));
      }
    }
  }
  sort(candidate.begin(), candidate.end());
  DSU::init(n);
  for (tuple<long long, int, int> e : candidate) {
    long long w, x, y;
    tie(w, x, y) = e;
    if (DSU::join(x, y)) Tree::addEdge(x, y, w);
  }
  Tree::dfs(1, 0);
  for (int i = 0; i < q; ++i) {
    int x;
    cin >> x;
    int y;
    cin >> y;
    cout << Tree::get(x, y) << "\n";
  }
}
