#include<iostream>
#include<cmath>
#include<vector>
#include<climits>
#include<cstdio>
#include<queue>

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)

using namespace std;

#define MAX 100100

typedef long long ll;

struct Edge {
  int s;
  ll w;
};

struct Data {
  int cur;
  ll w;
  bool operator < ( const Data &data ) const {
    if( w != data.w ) return w > data.w;
    return cur < data.cur;
  }
};

int V,E,R,Q;
ll x[MAX],y[MAX],z[MAX];
vector<Edge> G[MAX];
ll mini[20][MAX];

const bool debug = false;

void dijkstra(int mod) {
  rep(i,V+1) mini[mod][i] = LLONG_MAX;
  priority_queue<Data> Q;
  REP(i,1,V+1) if( i % R == mod ) {
    mini[mod][i] = 0;
    Q.push((Data){i,0});
  }
  while( !Q.empty() ) {
    Data data = Q.top(); Q.pop();
    rep(i,(int)G[data.cur].size()) {
      Edge &e = G[data.cur][i];
      if( mini[mod][e.s] > data.w + e.w ) {
	mini[mod][e.s] = data.w + e.w;
	Q.push((Data){e.s,mini[mod][e.s]});
      }
    }
  }
}

void compute() {
  rep(r,R) dijkstra(r);
  if( debug ) {
    rep(r,R) {
      puts("");
      cout << "mod R == " << r << endl;
      REP(i,1,V+1) {
	cout << "mini[" << r << "][" << i << "] = " << mini[r][i] << ", ";
      } puts("");
    }
  }

  ll ans = 0;
  rep(i,Q) {
    ll cost = LLONG_MAX;
    rep(r,R) {
      int Y = r;
      if( mini[r][x[i]] == LLONG_MAX || mini[Y][y[i]] == LLONG_MAX ) continue;
      cost = min(cost,
		 mini[r][x[i]]+mini[Y][y[i]]);
    }
    if( cost == LLONG_MAX ) continue;
    ans += max((ll)z[i]-cost,0LL);
  }
  cout << ans << endl;
}

int main() {
  cin >> V >> E >> R >> Q;
  rep(i,E) {
    int a,b,c;
    cin >> a >> b >> c;
    G[b].push_back((Edge){a,c});
  }
  rep(i,Q) {
    cin >> x[i] >> y[i] >> z[i];
  }
  compute();
  return 0;
}