#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<iostream>
#define int long long
using namespace std;
int n,m,k,p,head[600001],f[600001],fa[600001],vis[600001],ans,cnt,depth[600001];
struct edge{
	int next,to,data;
}e[600001];
int find(int x){
	if(fa[x]==x)return x;
	return fa[x]=find(fa[x]);
}
struct node{
	int to,data;
	bool operator <(const node &x)const{
		return data>x.data;
	}
}father[600001][31];
vector<node>g[600001];
struct ede{
	int x,y,z;
}a[600001];
void add_edge(int x,int y,int z){
	e[++cnt].next=head[x];
	e[cnt].to=y;
	e[cnt].data=z;
	head[x]=cnt;
}
void dijskstra(){
	priority_queue<node>q;
	memset(f,0x3f,sizeof(f));
	q.push((node){0,0});f[0]=0;
	while(!q.empty()){
		node x=q.top();q.pop();
		if(vis[x.to])continue;
		vis[x.to]=1;
		for(int i=head[x.to];i;i=e[i].next){
			if(!vis[e[i].to]&&f[x.to]+e[i].data<f[e[i].to]){
				f[e[i].to]=f[x.to]+e[i].data;
				q.push((node){e[i].to,f[e[i].to]});
			}
		}
	}
}
bool cmp(const ede &a,const ede &b){
	return a.z<b.z;
}
void dfs(int x,int pre){
	depth[x]=depth[pre]+1;
	for(int i=0;i<g[x].size();i++){
		if(g[x][i].to!=pre){
			dfs(g[x][i].to,x);
		}
		else{
			father[x][0].to=g[x][i].to;
			father[x][0].data=g[x][i].data;
		}
	}
}
int lca(int x,int y){
	if(depth[x]<depth[y])swap(x,y);
	int tot=0;
	for(int i=20;i>=1;i--)if(depth[father[x][i].to]>=depth[y])tot=max(tot,father[x][i].data),x=father[x][i].to;
	 if(x==y)return tot;
	 for(int i=20;i>=1;i--){
	 	if(father[x][i].to!=father[y][i].to)tot=max(tot,max(father[x][i].data,father[y][i].data)),x=father[x][i].to,y=father[y][i].to;
	 }
	 return max(tot,max(father[x][0].data,father[y][0].data));
} 
signed main(){
	scanf("%d%d%d%d",&n,&m,&k,&p);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
		add_edge(a[i].x,a[i].y,a[i].z);add_edge(a[i].y,a[i].x,a[i].z);
	}
	for(int i=1;i<=k;i++)add_edge(0,i,0),add_edge(i,0,0);
	dijskstra(); 
	for(int i=1;i<=m;i++)a[i].z+=f[a[i].y]+f[a[i].x];
    sort(a+1,a+m+1,cmp);memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)fa[i]=i;
	while(ans<n-1){
		for(int i=1;i<=m;i++){
			if(!vis[i]&&find(a[i].x)!=find(a[i].y)){
				fa[find(a[i].x)]=find(a[i].y);vis[i]=1;
				g[a[i].x].push_back((node){a[i].y,a[i].z});
				g[a[i].y].push_back((node){a[i].x,a[i].z});
				ans++;break;
			}
		}
	}
	dfs(1,0);
	for(int j=1;j<=20;j++){
	 for(int i=1;i<=n;i++){	
			father[i][j].to=father[father[i][j-1].to][j-1].to;
			father[i][j].data=max(father[i][j-1].data,father[father[i][j-1].to][j-1].data);
		}
	}
  for(int i=1;i<=p;i++){
		int a,b;
		cin>>a>>b;
		cout<<lca(a,b)<<endl;
	}
} 