#include <bits/stdc++.h>
using namespace std;
std::mt19937 rnd(
    (int)std::chrono::steady_clock::now().time_since_epoch().count());
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 10000;
const int MAXM = 10000;
const int MAXSPECIAL = 10;
const int MAXQ = 200000;
const int MAXW = 25;
const int MAXGN = MAXN;
const int MAXGM = MAXM;
void myassert(bool cond) { assert(cond); }
typedef struct MF {
  int n, m;
  int ghead[MAXGN], gnxt[2 * MAXGM], gto[2 * MAXGM];
  long long gcap[2 * MAXGM];
  void init(int _n) {
    n = _n, m = 0;
    for (int i = (0); i < (n); ++i) ghead[i] = -1;
  }
  void addedge(int a, int b, long long c) {
    gnxt[2 * m + 0] = ghead[a], ghead[a] = 2 * m + 0, gto[2 * m + 0] = b,
                 gcap[2 * m + 0] = c;
    gnxt[2 * m + 1] = ghead[b], ghead[b] = 2 * m + 1, gto[2 * m + 1] = a,
                 gcap[2 * m + 1] = 0;
    ++m;
  }
  int d[MAXGN];
  int q[MAXGN], qhead, qtail;
  int cur[MAXGN];
  long long dinic(int s, int t) {
    long long ret = 0;
    int niter = 0;
    while (true) {
      for (int i = (0); i < (n); ++i) d[i] = INT_MAX;
      qhead = qtail = 0;
      d[s] = 0, q[qhead++] = s;
      while (qtail < qhead && d[t] == INT_MAX) {
        int at = q[qtail++];
        for (int x = ghead[at]; x != -1; x = gnxt[x]) {
          int to = gto[x];
          if (gcap[x] == 0 || d[to] != INT_MAX) continue;
          d[to] = d[at] + 1;
          q[qhead++] = to;
        }
      }
      if (d[t] == INT_MAX) return ret;
      for (int i = (0); i < (n); ++i) cur[i] = ghead[i];
      ret += dfs(s, t, LLONG_MAX);
      ++niter;
    }
  }
  long long dfs(int at, int t, long long rem) {
    long long ret = 0;
    if (at == t) return rem;
    if (d[at] >= d[t]) return 0;
    for (; cur[at] != -1; cur[at] = gnxt[cur[at]]) {
      int to = gto[cur[at]];
      long long cap = gcap[cur[at]];
      if (d[to] != d[at] + 1 || cap == 0) continue;
      long long now = dfs(to, t, min(cap, rem));
      rem -= now;
      ret += now;
      if (gcap[cur[at]] != LLONG_MAX) gcap[cur[at]] -= now;
      if (gcap[cur[at] ^ 1] != LLONG_MAX) gcap[cur[at] ^ 1] += now;
      if (rem == 0) return ret;
    }
    return ret;
  }
  vector<int> findpath(int s, int t) {
    vector<int> ret;
    int at = s;
    while (at != t) {
      bool found = false;
      for (int x = ghead[at]; x != -1; x = gnxt[x]) {
        if (x % 2 != 0 || gcap[x ^ 1] == 0) continue;
        ++gcap[x], --gcap[x ^ 1], found = true;
        at = gto[x];
        ret.push_back(x);
        break;
      }
      myassert(found);
    }
    return ret;
  }
  vector<int> findreversepath(int s, int t) {
    vector<int> ret;
    int at = t;
    while (at != s) {
      bool found = false;
      for (int x = ghead[at]; x != -1; x = gnxt[x]) {
        if (x % 2 != 1 || gcap[x] == 0) continue;
        --gcap[x], ++gcap[x ^ 1], found = true, at = gto[x],
                                  ret.push_back(x ^ 1);
        break;
      }
      myassert(found);
    }
    reverse(ret.begin(), ret.end());
    return ret;
  }
} MF;
int n, m, nspecial, nq;
MF g;
int qval[MAXQ][MAXSPECIAL], qans[MAXQ];
int s, t;
int flowwith[1 << MAXSPECIAL];
int qsum[1 << MAXSPECIAL];
int bitcount[1 << MAXSPECIAL];
int currentflow;
bool active[MAXSPECIAL];
int calc(int mask) {
  int lo = 0, hi = INT_MAX;
  for (int done = (0); done < (1 << nspecial); ++done)
    if (flowwith[done] != -1) {
      if ((done & mask) == mask) {
        lo = max(lo, flowwith[done] - bitcount[done ^ mask] * MAXW);
        hi = min(hi, flowwith[done]);
      }
      if ((done & mask) == done) {
        lo = max(lo, flowwith[done]);
        hi = min(hi, flowwith[done] + bitcount[done ^ mask] * MAXW);
      }
    }
  if (lo == hi) return lo;
  for (int i = (0); i < (nspecial); ++i)
    if (mask & (1 << i)) {
      if (!active[i]) {
        assert(g.gcap[2 * i + 0] == 0 && g.gcap[2 * i + 1] == 0);
        g.gcap[2 * i + 0] = MAXW;
        active[i] = true;
      }
    } else {
      if (active[i]) {
        while (g.gcap[2 * i + 1] > 0) {
          int a = g.gto[2 * i + 1], b = g.gto[2 * i + 0];
          g.findreversepath(s, a);
          g.findpath(b, t);
          assert(g.gcap[2 * i + 1] > 0);
          --g.gcap[2 * i + 1];
          ++g.gcap[2 * i + 0];
          --currentflow;
        }
        assert(g.gcap[2 * i + 0] == MAXW);
        g.gcap[2 * i + 0] = 0;
        active[i] = false;
      }
    }
  currentflow += g.dinic(s, t);
  return currentflow;
}
void rec(int l, int r) {
  if (r - l <= 1) return;
  int m = l + (r - l) / 2;
  for (int mask = (0); mask < (1 << nspecial); ++mask)
    if (bitcount[mask] == m) flowwith[mask] = calc(mask);
  rec(l, m);
  rec(m, r);
}
void solve() {
  s = 0, t = n - 1;
  int initflow = g.dinic(s, t);
  bitcount[0] = 0;
  for (int mask = (1); mask < (1 << nspecial); ++mask)
    bitcount[mask] = bitcount[mask >> 1] + (mask & 1);
  currentflow = initflow;
  for (int i = (0); i < (nspecial); ++i) active[i] = false;
  for (int i = (0); i < (1 << nspecial); ++i) flowwith[i] = -1;
  flowwith[0] = calc(0);
  flowwith[(1 << nspecial) - 1] = calc((1 << nspecial) - 1);
  rec(0, nspecial);
  for (int i = (0); i < (nq); ++i) {
    qsum[0] = 0;
    for (int bit = (0); bit < (nspecial); ++bit)
      for (int mask = (0); mask < (1 << bit); ++mask)
        qsum[mask | (1 << bit)] = qsum[mask] + qval[i][bit];
    int cur = INT_MAX;
    for (int mask = (0); mask < (1 << nspecial); ++mask)
      cur = min(cur, flowwith[(1 << nspecial) - mask - 1] + qsum[mask]);
    qans[i] = cur;
  }
}
void run() {
  scanf("%d%d%d%d", &n, &m, &nspecial, &nq);
  g.init(n);
  for (int i = (0); i < (m); ++i) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    --a, --b;
    g.addedge(a, b, c);
  }
  for (int i = (0); i < (nq); ++i)
    for (int j = (0); j < (nspecial); ++j) scanf("%d", &qval[i][j]);
  solve();
  for (int i = (0); i < (nq); ++i) printf("%d\n", qans[i]);
}
int main() {
  run();
  return 0;
}
