#include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)
#define min(...) min({__VA_ARGS__})
#define max(...) max({__VA_ARGS__})

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

using pint = pair<int, int>;
using tint = tuple<int, int, int>;
using vint = vector<int>;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct edge {
  int to, cost;
  edge(){}
  edge(int to, int cost):to(to), cost(cost){}
};

int N, M, R, Q;
vector< vector<edge> > graph;
vector<int> mincost[11];

void dijkstra(int r) {
  mincost[r].resize(N+1, inf);
  priority_queue< pint, vector<pint>, greater<pint> > que;
  reps(i, 1, N+1) if(i%R == r) {
    mincost[r][i] = 0;
    que.emplace(0, i);
  }
  while(que.size()) {
    pint p = que.top(); que.pop();
    int v = p.second;
    if(mincost[r][v] < p.first) continue;
    for(edge& e : graph[v]) {
      if(e.cost + mincost[r][v] < mincost[r][e.to]) {
	mincost[r][e.to] = e.cost + mincost[r][v];
	que.emplace(mincost[r][e.to], e.to);
      }
    }
  }
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> N >> M >> R >> Q;
  graph.resize(N+1);
  rep(i, M) {
    int a, b, c;
    cin >> a >> b >> c; //--a, --b;
    graph[b].emplace_back(a, c);
  }
  rep(i, R) dijkstra(i);
  int ans = 0;
  rep(i, Q) {
    int x, y, z;
    cin >> x >> y >> z; //--x, --y;
    int tmp = 0;
    rep(j, R) chmax(tmp, z-mincost[j][x]-mincost[j][y]);
    ans += tmp;
  }
  cout << ans << endl;

  return 0;
}