#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int N = 300010;
const ll inf = 1e18;
struct edge{
int a,b;ll c;
}Edge[N];
bool cmp(edge a,edge b){
return a.c < b.c;
}
int n,m,k,q;
int idx,e[N],ne[N],h[N];ll w[N];
bool st[N];ll dist[N];
int p[N];
int dep[N],dp[N][30];
int cnt;ll val[N];
vector<int> G[N];
int find(int x){
if(p[x] != x)p[x] = find(p[x]);
return p[x];
}
void rebuild(){
cnt = n;
for(int i = 1;i<=m;i ++){
int u = find(Edge[i].a),v = find(Edge[i].b);
if(u == v)continue;
p[u] = p[v] = ++ cnt;
G[cnt].push_back(u);
G[cnt].push_back(v);
val[cnt] = Edge[i].c;
if(cnt == n * 2-1)break;
}
}
void add(int a,int b,ll c){
e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}
void dijkstra(){
priority_queue<pii,vector<pii> ,greater<pii> > q;
for(int i = 1;i<=n;i ++)dist[i] = inf;
for(int i = 1;i<=k;i ++){
dist[i] = 0;
q.push({0,i});
}
while(q.size()){
auto v = q.top();q.pop();
int t = v.second;
if(st[t])continue;
st[t] = true;
for(int i = h[t];~i;i = ne[i]){
int j = e[i];
if(dist[j] > dist[t] + w[i]){
dist[j] = dist[t] + w[i];
q.push({dist[j],j});
}
}
}
}
void dfs(int u,int f){
dep[u] = dep[f] + 1;
dp[u][0] = f;
for(int i = 1;(1 << i) <= dep[u];i ++)dp[u][i] = dp[dp[u][i-1]][i-1];
for(auto j:G[u]){
if(j == f)continue;
dfs(j,u);
}
}
int LCA(int x,int y){
if(dep[x] < dep[y])swap(x,y);
for(int i = 25;i >= 0;i --)if(dep[dp[x][i]] >= dep[y])x = dp[x][i];
if(x == y)return x;
for(int i = 25;i>= 0;i --)if(dp[x][i]!=dp[y][i])x = dp[x][i],y = dp[y][i];
return dp[x][0];
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m>>k>>q;
for(int i = 1;i<=m;i ++){
int a,b,c;cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
Edge[i] = {a,b,c};
}
sort(Edge+1,Edge + 1 + m,cmp);
for(int i = 1;i<=n*2;i ++)p[i] = i;
dijkstra();
for(int i = 1;i<=m;i ++){
int a = Edge[i].a,b = Edge[i].b;
Edge[i].c += dist[a] + dist[b];
}
rebuild();
dfs(cnt,0);
for(int i = 1;i<=q;i ++){
int x,y;cin>>x>>y;
cout<<val[LCA(x,y)]<<endl;
}
return 0;
}