#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define lowbit(x) ((x) & -(x))
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define YEE ios_base::sync_with_stdio(false); cin.tie(nullptr)
#define F first
#define S second
#define MP make_pair
#define EB emplace_back
#define PB push_back
#define INS insert
#define maxn 100005
using namespace std;
typedef long long loli;
typedef pair<int, loli> pii;
struct Edge {
    loli w;
    int to, pre;
    Edge(int a, int b, loli c) :
        to(a), pre(b), w(c) {}
    bool operator < (const Edge &a) const {
        return w > a.w;
    }
};

int Pt[maxn], s[maxn], p[maxn], dep[maxn], par[maxn][20];
loli dis[maxn], mx[maxn][20];
vector<pii> T[maxn], G[maxn];
vector<Edge> V;

int find(int  x) {
    return (p[x] == -1) ? x : (p[x] = find(p[x]));
}

bool join(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return false;
    if(s[x] < s[y]) swap(x, y);
    s[x] += s[y];
    p[y] = x;
    return true;
}

void dfs(int x, int p, int w) {
    mx[x][0] = w;
    par[x][0] = p;
    dep[x] = dep[p] + 1;
    for(int i = 1; i <= __lg(dep[x]); i++) {
        mx[x][i] = max(mx[x][i - 1], mx[par[x][i - 1]][i - 1]);
        par[x][i] = par[par[x][i - 1]][i - 1];
    }
    for(auto e : T[x]) {
        if(e.F == p) continue;
        dfs(e.F, x, e.S);
    }
}

loli cal(int a, int b) {
    if(dep[a] < dep[b])
        swap(a, b);
    int dif = dep[a] - dep[b];
    loli ret = 0;
    for(int i = 0; dif; i++) {
        if(dif & 1) {
            ret = max(ret, mx[a][i]);
            a = par[a][i];
        }
        dif >>= 1;
    }
    if(a == b) return ret;
    for(int i = __lg(dep[a]); i >= 0; i--) {
        if(par[a][i] != par[b][i]) {
            ret = max(ret, mx[a][i]);
            ret = max(ret, mx[b][i]);
            a = par[a][i];
            b = par[b][i];
        }
    }
    ret = max(ret, mx[a][0]);
    ret = max(ret, mx[b][0]);
    return ret;
}

int n, m, k, q;

int main() {
    YEE;
    cin >> n >> m >> k >> q;
    for(int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u].EB(v, w);
        G[v].EB(u, w);
    }
    for(int i = 1; i <= n; i++) {
        s[i] = 1; p[i] = -1;
        Pt[i] = -1;
    }
    priority_queue<Edge> pq;
    for(int i = 1; i <= k; i++) {
        pq.push({i, i, 0});
    }
    while(pq.size()) {
        auto cur = pq.top(); pq.pop();
        if(Pt[cur.to] != -1)
            continue;
        Pt[cur.to] = cur.pre;
        dis[cur.to] = cur.w;
        for(auto e : G[cur.to]) {
            pq.emplace(e.F, cur.pre, cur.w + e.S);
        }
    }
    for(int i = 1; i <= n; i++) {
        for(auto e : G[i]) {
            if(Pt[i] != Pt[e.F]) {
                V.EB(Pt[i], Pt[e.F], dis[i] + dis[e.F] + e.S);
            }
        }
    }
    sort(rall(V)); int cnt = 0;
    for(auto e : V) {
        if(join(e.to, e.pre)) {
            T[e.to].EB(e.pre, e.w);
            T[e.pre].EB(e.to, e.w);
            cnt++;
        }
    }
    assert(cnt == k - 1);
    dep[0] = 0;
    dfs(1, 0, 0);
    int a, b;
    while(q--) {
        cin >> a >> b;
        cout << cal(a, b) << '\n';
    }
    return 0;
}


