#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
char open[100000 + 5][55];
int n, m, d;
namespace Tarjan {
const int MAXN = 5e6 + 5;
const int MAXM = 6e6 + 5;
struct Edge {
  int to, nxt;
} edge[MAXM];
int head[MAXN], tot;
int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN], vis[MAXN];
int Index, top;
int scc, s, t;
bool Instack[MAXN];
int num[MAXN];
inline void addedge(int u, int v) {
  edge[tot].to = v;
  edge[tot].nxt = head[u];
  head[u] = tot++;
}
inline void Tarjan(int u) {
  int v;
  Low[u] = DFN[u] = ++Index;
  Stack[top++] = u;
  Instack[u] = true;
  for (int i = head[u]; ~i; i = edge[i].nxt) {
    v = edge[i].to;
    if (!DFN[v]) {
      Tarjan(v);
      if (Low[u] > Low[v]) Low[u] = Low[v];
    } else if (Instack[v] && Low[u] > DFN[v])
      Low[u] = DFN[v];
  }
  if (Low[u] == DFN[u]) {
    scc++;
    do {
      v = Stack[--top];
      Instack[v] = false;
      Belong[v] = scc;
      s = v / n, t = v % n;
      if (open[t][s] == '1' && vis[t] != scc) {
        num[scc]++;
        vis[t] = scc;
      }
    } while (v != u);
  }
}
void solve(int N) {
  memset(DFN, 0, sizeof(DFN));
  memset(Instack, false, sizeof(Instack));
  memset(num, 0, sizeof(num));
  Index = scc = top = 0;
  Tarjan(0);
}
void init() {
  tot = 0;
  memset(head, -1, sizeof(head));
}
}  // namespace Tarjan
using namespace Tarjan;
struct Edge {
  struct edge {
    int to, nxt;
  } edge[MAXM];
  int head[MAXN], tot;
  void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
  }
  void addedge(int u, int v) {
    edge[tot].to = v;
    edge[tot].nxt = head[u];
    head[u] = tot++;
  }
} T;
inline int getid(int id, int dep) { return dep * n + id; }
queue<int> Q;
inline void bfs(int &ans) {
  int st = Belong[0];
  Q.push(st);
  vis[st] = num[st];
  while (!Q.empty()) {
    int now = Q.front();
    ans = max(ans, vis[now]);
    Q.pop();
    for (int i = T.head[now]; ~i; i = T.edge[i].nxt) {
      int v = T.edge[i].to;
      vis[v] = max(vis[v], num[v] + vis[now]);
      DFN[v]--;
      if (DFN[v] == 0) Q.push(v);
    }
  }
}
int main() {
  init();
  T.init();
  scanf("%d%d%d", &n, &m, &d);
  for (int i = 0; i < m; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    u--, v--;
    for (int j = 0; j < d; j++) {
      int s = getid(u, j);
      int t = getid(v, (j + 1) % d);
      addedge(s, t);
    }
  }
  for (int i = 0; i < n; i++) scanf("%s", open[i]);
  int tot = n * d;
  solve(tot);
  memset(DFN, 0, sizeof(DFN));
  for (int i = 0; i < tot; i++) {
    for (int j = head[i]; ~j; j = edge[j].nxt) {
      int v = edge[j].to;
      int s = Belong[i], t = Belong[v];
      if (s == t || t == 0 || s == 0) continue;
      T.addedge(s, t);
      DFN[t]++;
    }
  }
  int ans = 0;
  memset(vis, 0, sizeof(vis));
  bfs(ans);
  printf("%d\n", ans);
  return 0;
}
