#include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
const int N = 1e5 + 1, D = 52, M = N * D;
int n, d, To[M], Ne[M], St[M], en, dfn[M], low[M], st[M], stop, blk[M], bln,
    wg[M];
int Top[M], Nep[M], Stp[M], enp, f[M];
bool vi[M], ins[M];
char mp[N][D];
void addedge(int u, int v) { To[++en] = v, Ne[en] = St[u], St[u] = en; }
void addedgep(int u, int v) { Top[++enp] = v, Nep[enp] = Stp[u], Stp[u] = enp; }
void tarjan(int u) {
  static int ts = 0;
  dfn[u] = low[u] = ++ts;
  st[++stop] = u, ins[u] = 1;
  for (int i = St[u]; i; i = Ne[i]) {
    if (dfn[To[i]] == 0) {
      tarjan(To[i]);
      low[u] = min(low[u], low[To[i]]);
    } else if (ins[To[i]])
      low[u] = min(low[u], dfn[To[i]]);
  }
  if (dfn[u] == low[u]) {
    ++bln;
    for (int tmp = -1; tmp != u;) {
      tmp = st[stop--], ins[tmp] = 0;
      blk[tmp] = bln;
    }
  }
}
void Dfs(int u) {
  if (vi[u])
    return;
  else
    vi[u] = 1;
  for (int i = Stp[u]; i; i = Nep[i]) {
    Dfs(Top[i]);
    f[u] = max(f[u], f[Top[i]]);
  }
  f[u] += wg[u];
}
int main() {
  int m;
  scanf("%d%d%d", &n, &m, &d);
  for (int i = 1, u, v; i <= m; ++i) {
    scanf("%d%d", &u, &v);
    for (int t = 0; t < d; ++t)
      addedge((((u)-1) * d + (t) + 1),
              (((v)-1) * d + ((t + 1 == d ? 0 : t + 1)) + 1));
  }
  for (int i = 1; i <= n; ++i) scanf("%s", mp[i]);
  tarjan((((1) - 1) * d + (0) + 1));
  static vector<int> tmp;
  for (int u = 1; u <= n; ++u) {
    for (int t = 0; t < d; ++t) {
      if (mp[u][t] == '1') tmp.push_back(blk[(((u)-1) * d + (t) + 1)]);
      for (int i = St[(((u)-1) * d + (t) + 1)]; i; i = Ne[i])
        if (blk[(((u)-1) * d + (t) + 1)] != blk[To[i]])
          addedgep(blk[(((u)-1) * d + (t) + 1)], blk[To[i]]);
    }
    sort(tmp.begin(), tmp.end()),
        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
    for (int x : tmp) ++wg[x];
    tmp.clear();
  }
  Dfs(blk[(((1) - 1) * d + (0) + 1)]);
  printf("%d\n", f[blk[(((1) - 1) * d + (0) + 1)]]);
  return 0;
}
