#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
ifstream f("amenzi.in");
ofstream g("amenzi.out");
struct amenzi{
int n,t,val;
}v[12005];
int n,m,p,k,a[155][155],x,y,c,u;
int arb[155][3505],mx,d,node,r,fl;
///roy floyd pt distante minime intre noduri
///sortez infractiunile dupa timp
///pt infractiunea curenta caut una recenta de la care pot ajunge cu bani maximi
///querurile iar sortate si mers tot la fel
void talktomebaby()
{
for(int K=1;K<=n;++K) for(int i=1;i<=n;++i) for(int j=1;j<=n;++j)
if(i!=K && j!=K && a[i][K] && a[K][j] && (a[i][K]+a[K][j]<a[i][j] || a[i][j]==0)) a[i][j]=a[j][i]=a[i][K]+a[K][j];
}
bool comp(amenzi a,amenzi b){return(a.t<b.t);}
void update(int i,int nod,int lt,int rt,int poz)
{
if(lt==rt)
{
arb[i][nod]=u;
return;
}
int md=(lt+rt)/2;
if(poz<=md) update(i,nod*2,lt,md,poz);
else update(i,nod*2+1,md+1,rt,poz);
arb[i][nod]=max(arb[i][nod*2],arb[i][nod*2+1]);
}
void query(int i,int nod,int lt,int rt,int x,int y)
{
if(x>rt || y<lt) return;
if(x<=lt && rt<=y)
{
r=max(r,arb[i][nod]);
return;
}
int md=(lt+rt)/2;
if(md>=x) query(i,nod*2,lt,md,x,y);
if(md<y) query(i,nod*2+1,md+1,rt,x,y);
}
void thismadnesssogoodforme()
{
for(int i=1;i<=k;++i)
{
node=v[i].n; mx=0;
for(int j=1;j<=n;++j) if(node==j || a[node][j])
{
d=v[i].t-a[node][j]; r=0;
query(j,1,0,3500,0,d);
mx=max(mx,r);
}
u=v[i].val+mx;
if(mx==0)
{
d=-1;
if(a[node][1] || node==1) d=v[i].t-a[node][1];
}
if(d>=0) update(node,1,0,3500,v[i].t);
}
}
void thatsthatshitivebeenon()
{
for(int i=1;i<=p;++i)
{
f>>node>>fl; mx=0;
for(int j=1;j<=n;++j) if(node==j || a[node][j])
{
d=fl-a[node][j]; r=0;
query(j,1,0,3500,0,d);
mx=max(mx,r);
}
g<<mx<<'\n';
}
}
int main()
{
f>>n>>m>>k>>p;
for(int i=1;i<=m;++i) {f>>x>>y>>c; a[x][y]=a[y][x]=c;}
talktomebaby();
for(int i=1;i<=k;++i) {f>>v[i].n>>v[i].t>>v[i].val;}
sort(v+1,v+k+1,comp);
thismadnesssogoodforme();
thatsthatshitivebeenon();
return 0;
}