#include <bits/stdc++.h>
#define ll long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
namespace IO{
  inline char ch(){
    static char s[1<<16],*S,*T;
    return (S == T)&&(T = (S = s)+
      fread(s,1,1<<16,stdin),S == T)?EOF:*S++;
  }
  template<typename T> void read(T &x){
    x = 0; int f(1); char c = ch();
    for(;!isdigit(c);c = ch()) if(c == '-') f = -1;
    for(;isdigit(c);c = ch()) x = x*10+c-'0';
    x *= f;
  }
}
using namespace IO;
const int maxn = 100003;
const int maxm = 300003;
int K,n,m,Q,N,fa[maxn*2][19];
int uno[maxn*2],lg[2*maxn],dep[2*maxn];
ll dp[maxn*2][19],val[maxn*2];
int find(int x){
  return x == uno[x]?x:uno[x] = find(uno[x]);
}
struct Graph{
  int hd[maxn*2],cnt;
  struct edge{int ed,nxt; ll len;}e[2*maxm];
  inline void star(int u,int v,ll l){
    e[++cnt] = (edge){v,hd[u],l};
    hd[u] = cnt;
  }
}G,T;
int tot;
struct NGedge{
  int u,v; ll l;
  inline bool operator <(const NGedge &o)const{
    return l < o.l;
  }
}E[maxm];
int col[maxn],vis[maxn];
ll Dis[maxn];
struct node{
  int vl,id;
  inline bool operator <(const node &o)const{
    return vl > o.vl;
  }
};
priority_queue<node> hp;
void Dijkstra(){
  for(int i = K+1;i <= n;++i) Dis[i] = 1e16;
  for(int i(1);i <= K;++i) hp.push((node){0,i}),col[i] = i;
  while(!hp.empty()){
    node u = hp.top(); hp.pop();
    if(vis[u.id]) continue;
    vis[u.id] = 1;
    for(int i = G.hd[u.id];i;i = G.e[i].nxt){
      int v = G.e[i].ed;
      if(Dis[v] > Dis[u.id]+G.e[i].len){
        Dis[v] = Dis[u.id]+G.e[i].len;
        col[v] = col[u.id];
        hp.push((node){Dis[v],v});
      }
    }
  }
}
void Dfs(int x,int FA){
  fa[x][0] = FA;
  dep[x] = dep[FA]+1;
  dp[x][0] = val[x];
  for(int i(1);i < lg[dep[x]];++i){
    fa[x][i] = fa[fa[x][i-1]][i-1];
    dp[x][i] = max(dp[x][i-1],dp[fa[x][i-1]][i-1]);
  }
  for(int i = T.hd[x];i;i = T.e[i].nxt){
    int y = T.e[i].ed;
    Dfs(y,x);
  }
}
ll LCA(int x,int y){
  ll ret = 0;
  while(dep[x] != dep[y]){
    if(dep[x] < dep[y]) swap(x,y);
    ret = max(ret,dp[x][lg[dep[x]-dep[y]]-1]);
    x = fa[x][lg[dep[x]-dep[y]]-1];
  }
  if(x == y) return max(ret,val[x]);
  for(int i = lg[dep[x]]-1;i >= 0;--i)
    if(fa[x][i] != fa[y][i]){
      ret = max(ret,dp[x][i]);
      ret = max(ret,dp[y][i]);
      x = fa[x][i]; y = fa[y][i];
    }
  return max(ret,val[fa[x][0]]);
}
int main(){
#ifdef LZX_CAI
  freopen("test.in","r",stdin);
  freopen("test.out","w",stdout);
#endif
  read(n);
  read(m);
  read(K);
  read(Q);
  for(int i(1);i <= m;++i){
    int u,v,l;
    read(u);
    read(v);
    read(l);
    G.star(u,v,l);
    G.star(v,u,l);
  }
  Dijkstra();
  for(int i(1);i <= n;++i)
    for(int j = G.hd[i];j;j = G.e[j].nxt){
      int k = G.e[j].ed;
      if(col[i] == col[k]) continue;
      if(i > k) continue;
      E[++tot] = (NGedge){col[i],col[k],G.e[j].len+Dis[i]+Dis[k]};
    }
  sort(E+1,E+1+tot);
  for(int i(1);i <= K;++i) uno[i] = i;
  N = K;
  for(int i(1);i <= tot;++i){
    int u = E[i].u;
    int v = E[i].v;
    int uf = find(u);
    int vf = find(v);
    if(uf == vf) continue;
    ++N; val[N] = E[i].l;
    uno[uf] = uno[vf] = N;
    uno[N] = N;
    T.star(N,uf,0);
    T.star(N,vf,0);
  }
  for(int i(1);i <= N;++i)
    lg[i] = lg[i-1]+(1<<lg[i-1] == i);
  dep[0] = -1; Dfs(N,0);
  for(int i(1);i <= Q;++i){
    int x,y;
    read(x);
    read(y);
    ll Ans = LCA(x,y);
    printf("%lld\n",Ans);
  }
  return 0;
}