#include <bits/stdc++.h>
void err() { std::cout << '\n'; }
template <typename T, typename... Args>
void err(T a, Args... args) {
  std::cout << a << ' ';
  err(args...);
}
void pt() { std::cout << '\n'; }
template <typename T, typename... Args>
void pt(T a, Args... args) {
  std::cout << a << ' ';
  pt(args...);
}
using namespace std;
const int N = 1e5 + 5, M = 4e5 + 5;
struct Edge {
  int v, w, next;
} e[M << 1];
long long dis[N];
struct Dijkstra {
  struct node {
    long long d, u;
    bool operator<(const node &A) const { return d > A.d; }
  };
  int head[N], tot;
  bool vis[N];
  void init() {
    memset(head, -1, sizeof(head));
    tot = 0;
  }
  void adde(int u, int v, int w) {
    e[tot].v = v;
    e[tot].w = w;
    e[tot].next = head[u];
    head[u] = tot++;
  }
  void dij(int s) {
    priority_queue<node> q;
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[s] = 0;
    q.push(node{0, s});
    while (!q.empty()) {
      node cur = q.top();
      q.pop();
      int u = cur.u, d = cur.d;
      if (vis[u]) continue;
      vis[u] = 1;
      for (int i = head[u]; i != -1; i = e[i].next) {
        int v = e[i].v;
        if (dis[v] > dis[u] + e[i].w) {
          dis[v] = dis[u] + e[i].w;
          q.push(node{dis[v], v});
        }
      }
    }
  }
} solver;
int n, m, k, q;
struct E {
  int u, v;
  long long w;
  bool operator<(const E &A) const { return w < A.w; }
} edge[M << 1];
vector<pair<int, int> > v[N], edges[N];
long long ans[M];
int f[N];
int find(int x) { return f[x] == x ? f[x] : f[x] = find(f[x]); }
set<int> s[N];
void merge(int x, int y, long long z) {
  for (auto it : s[x]) {
    for (auto t : v[it]) {
      if (s[y].find(t.first) != s[y].end()) {
        ans[t.second] = z;
      }
    }
    s[y].insert(it);
  }
  s[x].clear();
  f[x] = y;
}
void Union(int x, int y, long long z) {
  int fx = find(x), fy = find(y);
  if (fx != fy) {
    if ((int)(s[fx]).size() < (int)(s[fy]).size()) {
      merge(fx, fy, z);
    } else {
      merge(fy, fx, z);
    }
  }
}
void run() {
  solver.init();
  for (int i = 1; i <= m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    solver.adde(u, v, w);
    solver.adde(v, u, w);
    edges[u].push_back(make_pair(v, w));
  }
  for (int i = 1; i <= k; i++) solver.adde(0, i, 0);
  solver.dij(0);
  m = 0;
  for (int u = 1; u <= n; u++) {
    for (auto it : edges[u]) {
      int v = it.first, w = it.second;
      edge[++m] = E{u, v, dis[u] + dis[v] + w};
    }
  }
  for (int i = 1; i <= q; i++) {
    int a, b;
    cin >> a >> b;
    v[a].push_back(make_pair(b, i));
    v[b].push_back(make_pair(a, i));
  }
  memset(ans, 0x3f3f3f3f, sizeof(ans));
  sort(edge + 1, edge + m + 1);
  for (int i = 1; i <= n; i++) f[i] = i, s[i].insert(i);
  for (int i = 1; i <= m; i++) {
    int u = edge[i].u, v = edge[i].v;
    long long w = edge[i].w;
    Union(u, v, w);
  }
  for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cout << fixed << setprecision(20);
  while (cin >> n >> m >> k >> q) run();
  return 0;
}
