#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define FAST ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cerr.tie(0)
#define mp make_pair
#define xx first
#define yy second
#define pb push_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define all(x) (x).begin(),(x).end()
#define inv(n) power((n), mod - 2)
#define ff(i,a,b) for (int (i) = (a); (i) < (b); (i)++)
#define fff(i,a,b) for (int (i) = (a); (i) <= b; (i)++)
#define bff(i,a,b) for (int (i) = (b)-1; (i) >= (a); (i)--)
#define bfff(i,a,b) for (int (i) = (b); (i) >= (a); (i)--)
#define sum_overflow(a,b) __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
#define mul_overflow(a,b) __builtin_mul_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)

using namespace std;
long double typedef ld;
unsigned int typedef ui;
long long int typedef li;
pair<int,int> typedef pii;
pair<li,li> typedef pli;
pair<ld,ld> typedef pld;
vector<vector<int>> typedef graph;
unsigned long long int typedef ull;
const ld PI = 3.14159265359;
//const int mod = 998244353;
const int mod = 1000000007;
const li inf = ((1ll<<63)-1-(1ll<<31));

using namespace __gnu_pbds;
template <class T> using oset = tree<T, null_type,less<T>, rb_tree_tag,tree_order_statistics_node_update>;
template <class T> using omset = tree<T, null_type,less_equal<T>, rb_tree_tag,tree_order_statistics_node_update>;

inline int power(li _a, int _n)
{
    li _c=1;
    while (_n>0)
    {
        if (_n%2) _c=_c*_a%mod;
        _a=_a*_a%mod; _n/=2;
    } return _c;
}

template<typename _broj> _broj _nzd(_broj _a, _broj _b, pair<_broj,_broj> &_r)
{
    if (_b==0)
    {
        _r={1,0};
        return _a;
    }

    _broj _d=_nzd(_b,_a%_b,_r);
    _r={_r.yy,_r.xx-(_a/_b)*_r.yy};

    return _d;
}
template<typename _broj> _broj nzd(_broj _a, _broj _b, pair<_broj,_broj> &_r)
{
    if (abs(_a)<abs(_b))
    {
        _broj d=_nzd(_b,_a,_r);
        _r={_r.yy,_r.xx}; return d;
    }
    return _nzd(_a,_b,_r);
}
template <typename _broj> _broj bigmod(_broj _a, _broj _b, _broj _m)
{
    if (_b==0) return 0;
    if (_b&1) return (bigmod(_a,_b-1,_m)+_a)%_m;
    return (bigmod(_a,_b/2,_m)*2)%_m;
}
template<typename _broj> _broj kinez(_broj _a, _broj _n, _broj _b, _broj _m)
{
    if (_a==_b) return _a;
    _a%=_n; if (_a<0) _a+=_n;
    _b%=_m; if (_b<0) _b+=_m;

    pli _r;
    li _d=nzd(_n,_m,_r);
    if ((_b-_a)%_d) return -1;
    li _res,_mod=_n/__gcd(_n,_m)*_m;
    _r.xx%=_mod/_n; if (_r.xx<0) _r.xx+=_mod/_n;
    li _mnoz=(_b-_a)/_d; _mnoz%=_mod; if (_mnoz<0) _mnoz+=_mod;
    _r.xx=bigmod(_r.xx,_mnoz,_mod);
    _res=(bigmod(_r.xx,_n,_mod)+_a)%_mod;
    if (_res<0) _res+=_mod; return _res;
}

inline li sum(int _n) {return ((li)_n*(_n+1))/2;}

inline li kv(int _n) {return ((li)_n*(_n+1)*(2*_n+1))/6;}







//Note to self: Check for overflow

struct edge{
    int u,v,w;
};
struct bogosort{
    bool operator()(edge a, edge b){
        return a.w<b.w;
    }
};

vector<pii> g[100003];
bitset<100003> vis;
int d[100003];

struct dsu
{
    int up[100003];

    void resize(int n){
        fff(i,1,n) up[i]=-1;
    }

    int Up(int x)
    {
        if (up[x]<0) return x;
        up[x]=Up(up[x]); return up[x];
    }
    bool spoji(int a, int b)
    {
        a=Up(a),b=Up(b);
        if (a==b) return false;
        if (up[a]>up[b])
        {
            up[b]+=up[a];
            up[a]=b;
        }
        else
        {
            up[a]+=up[b];
            up[b]=a;
        } return true;
    }
} DS;

int vr=1;
int tin[100003];
int tout[100003];
int up[20][100003];
int mx[20][100003];

void dfs(int p, int q, int ew)
{
    tin[p]=vr++; up[0][p]=q; mx[0][p]=ew;
    for (auto [w,it] : g[p]) if (it!=q) dfs(it,p,w);
    tout[p]=vr++;
}

bool anc(int a, int b){
    return tin[a]<=tin[b] && tout[a]>=tout[b];
}
int qry(int a, int b)
{
    int res=0;

    bff(k,0,20) if (!anc(up[k][a],b))
        res=max(res,mx[k][a]),a=up[k][a];
    if (!anc(a,b))
        res=max(res,mx[0][a]),a=up[0][a];

    bff(k,0,20) if (!anc(up[k][b],a))
        res=max(res,mx[k][b]),b=up[k][b];
    if (!anc(b,a))
        res=max(res,mx[0][b]),b=up[0][b];

    return res;
}

int main()
{
    FAST;

    int n,m,k,q;
    cin>>n>>m>>k>>q;
    vector<edge> ed(m);
    ff(i,0,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        ed[i]={u,v,w};
        g[u].pb(mp(w,v));
        g[v].pb(mp(w,u));
    }

    priority_queue<pii,vector<pii>,greater<pii>> dj;
    fff(i,1,k) dj.push({0,i});
    while (!dj.empty())
    {
        auto [nw,u]=dj.top(); dj.pop();
        if (vis[u]) continue; vis[u]=1; d[u]=nw;
        for (auto [ew,v] : g[u]) dj.push({nw+ew,v});
    }
    ff(i,0,m) ed[i].w+=d[ed[i].u]+d[ed[i].v];

    sort(all(ed),bogosort());
    DS.resize(n); fff(i,1,n) g[i].clear();
    for (auto [u,v,w] : ed)
        if (DS.spoji(u,v))
            g[u].pb({w,v}),g[v].pb({w,u});

    dfs(1,0,0); tout[0]=vr;
    ff(i,1,20) fff(j,1,n)
        up[i][j]=up[i-1][up[i-1][j]],
        mx[i][j]=max(mx[i-1][j],mx[i-1][up[i-1][j]]);

    /*fff(i,0,5)
    {
        fff(j,1,n) cout<<up[i][j]<<" ";
        cout<<endl;
    } cout<<endl;

    fff(i,0,5)
    {
        fff(j,1,n) cout<<mx[i][j]<<" ";
        cout<<endl;
    } cout<<endl;*/

    while (q--)
    {
        int a,b; cin>>a>>b;
        cout<<qry(a,b)<<"\n";
    }
}

//Note to self: Check for overflow

/*

5 5 1 0
1 2 1
2 3 4
3 4 7
4 5 5
5 1 3

7 6 7 1000
1 2 1
1 3 1
2 4 1
2 5 1
3 6 1
3 7 1

*/
