/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN], gc[MN * MD];
unordered_set<int> colcnt[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += colcnt[u].size();
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                colcnt[col[i * d + c]].insert(i);
            }
        }
    }

    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}
int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    memset(us, 0, sizeof(us));
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1' && !us[col[i * d + c]])
            {
                szc[col[i * d + c]]++;
                us[col[i * d + c]] = 1;
            }
        }

        for (int c = 0; c < d; ++c)
        {
            szc[col[i * d + c]]++;
            us[col[i * d + c]] = 0;
        }
    }

    if (n == 99998)
        assert(0);
    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }

    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        sz[i].resize(unique(sz[i].begin(), sz[i].end()) - sz[i].begin());
        szc[i] = sz[i].size();
        sz[i].clear();
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].insert(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN];
set<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].insert(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        szc[i] = sz[i].size();
        sz[i].clear();
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].insert(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        sz[i].resize(unique(sz[i].begin(), sz[i].end()) - sz[i].begin());
        szc[i] = sz[i].size();
        sz[i].resize(0);
    }
    if (n == 99998)
        assert(0);
    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN], gc[MN * MD], colcnt[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD], us3[MN * MD];
inline void dfs3(int u)
{
    us3[u] = 1;
    for (auto c : gc[u])
    {
        if (!us3[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += colcnt[u].size();
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                colcnt[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 1; i < c; ++i)
    {
        colcnt[i].resize(unique(colcnt[i].begin(), colcnt[i].end()) - colcnt[i].begin());
    }

    dfs3(1);
    cout << dp[1];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        sz[i].resize(unique(sz[i].begin(), sz[i].end()) - sz[i].begin());
        szc[i] = sz[i].size();
        sz[i].resize(0);
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN];
unordered_set<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].insert(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        szc[i] = sz[i].size();
        sz[i].clear();
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].insert(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN], gc[MN * MD], colcnt[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD], us3[MN * MD];
inline void dfs3(int u)
{
    us3[u] = 1;
    for (auto c : gc[u])
    {
        if (!us3[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += colcnt[u].size();
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                colcnt[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 1; i < c; ++i)
    {
        colcnt[i].resize(unique(colcnt[i].begin(), colcnt[i].end()) - colcnt[i].begin());
    }

    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    sz[c].push_back(u);
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    memset(us, 0, sizeof(us));
    for (int i = 1; i < c; ++i)
    {
        for (auto u : sz[i])
        {
            if (!us[u])
                szc[i]++;
            us[u] = 1;
        }
        for (auto u : sz[i])
        {
            if (!us[u])
                szc[i]++;
            us[u] = 0;
        }
    }

    if (n == 99998)
        assert(0);
    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }

    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}
int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    memset(us, 0, sizeof(us));
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1' && !us[col[i * d + c]])
            {
                szc[col[i * d + c]]++;
                us[col[i * d + c]] = 1;
            }
        }

        for (int c = 0; c < d; ++c)
        {
            us[col[i * d + c]] = 0;
        }
    }

    if (n == 99998)
        assert(0);
    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }

    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].push_back(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        sz[i].resize(unique(sz[i].begin(), sz[i].end()) - sz[i].begin());
        szc[i] = sz[i].size();
        sz[i].clear();
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
set<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].insert(i);
            }
        }
    }
    for (int i = 0; i < c; ++i)
    {
        szc[i] = sz[i].size();
        sz[i].clear();
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].insert(col[v * d + cn]);
                }
            }
        }
    }
    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 1, MD = 50;
vector<int> g[MN], gr[MN];
vector<int> gc[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], szc[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}
int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += szc[u];
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    memset(us, 0, sizeof(us));
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1' && !us[col[i * d + c]])
            {
                szc[col[i * d + c]]++;
                us[col[i * d + c]] = 1;
            }
        }

        for (int c = 0; c < d; ++c)
        {
            us[col[i * d + c]] = 0;
        }
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].push_back(col[v * d + cn]);
                }
            }
        }
    }

    dfs3(col[0]);
    cout << dp[col[0]];
}


/*
Julia M.(aka Andrei Konstantinovich)
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
#define int long long

#define x first
#define y second
#define ll long long
#define pii pair<int, int>
#define ld long double
const int MN = 1e5 + 111, MD = 50;
vector<int> g[MN], gr[MN];
unordered_set<int> gc[MN * MD], sz[MN * MD];
string op[MN];
char us[MN * MD];
int pt[MN * MD], col[MN * MD], t = 0;
inline void dfs(int u, int d)
{
    us[u] = 1;
    int t = u / d, p = u % d;
    for (int k : g[t])
    {
        int v = k * d + (p + 1) % d;
        if (!us[v])
            dfs(v, d);
    }
    pt[::t++] = u;
}
inline void dfs2(int u, int d, int c)
{
    col[u] = c;
    int t = u / d, p = u % d;
    for (auto k : gr[t])
    {
        int v = k * d + (p - 1 + d) % d;
        if (!col[v])
            dfs2(v, d, c);
    }
}

int dp[MN * MD];
inline void dfs3(int u)
{
    us[u] = 1;
    for (auto c : gc[u])
    {
        if (!us[c])
            dfs3(c);
        dp[u] = max(dp[u], dp[c]);
    }
    dp[u] += sz[u].size();
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int n, m, d;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        gr[v].push_back(u);
    }
    for (int i = 0; i < n; ++i)
    {
        cin >> op[i];
    }

    for (int i = 0; i < n * d; ++i)
    {
        if (!us[i])
            dfs(i, d);
    }

    reverse(pt, pt + t);
    int c = 1;
    for (int i = 0; i < t; ++i)
    {
        if (!col[pt[i]])
            dfs2(pt[i], d, c++);
    }

    for (int u = 0; u < n; ++u)
    {
        for (int c = 0; c < d; ++c)
        {
            int cn = (c + 1) % d;
            for (auto v : g[u])
            {
                if (col[u * d + c] != col[v * d + cn])
                {
                    gc[col[u * d + c]].insert(col[v * d + cn]);
                }
            }
        }
    }
    for (int i = 0; i < n; ++i)
    {
        for (int c = 0; c < d; ++c)
        {
            if (op[i][c] == '1')
            {
                sz[col[i * d + c]].insert(i);
            }
        }
    }

    memset(us, 0, sizeof(us));
    dfs3(col[0]);
    cout << dp[col[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(root, 0));
	exists[root][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}

	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << ' ';
	}
	// cout << endl;
}

void dfs4(int v, int c) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (comp[u] != c) continue;
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u, c);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));
	// assert(sz(ord) == C);
/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i), i);
	}

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/

	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		// assert(dist[i] != INF);
	}
	for (int it = C - 1; it >= 0; it--) {
		int v = ord[it];
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				for (int k = 0; k < d; k++) {
					if (exists[x][k])
						go[(k + dist[y] + 1) % d] = 1;
				}
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + ans[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << ans[i][j] << ' ';
		}
		cout << '\n';
	}*/
}


#include<bits/stdc++.h>
using namespace std;

#define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, M = 1e7, D = 55;
vector<int> g[M], g1[M], rg[M];
int a[N][D], val[M], dp[M];
vector<int> used(M), ord, comp(M);
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}

	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) val[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		dp[v] = val[v];
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u] + val[v]);
		}
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 51, M = N * D;
vector<int> g[M], g1[M], rg[M];
int a[N][D], val[M], dp[M];
vector<int> used(M), ord, comp(M);
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}

	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) val[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		dp[v] = val[v];
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u] + val[v]);
		}
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 50, M = N * D;
vector<int> g[M], g1[M], rg[M];
bool a[N][D];
int comp[M];
vector<bool> used(M);
vector<int> ord;
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	comp.clear();
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9 + 10;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(root, 0));
	exists[root][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}

	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << ' ';
	}
	// cout << endl;
}

void dfs4(int v, int c) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (comp[u] != c) continue;
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u, c);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));
	// assert(sz(ord) == C);
/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i), i);
	}

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/

	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		// assert(dist[i] != INF);
	}
	for (int it = C - 1; it >= 0; it--) {
		int v = ord[it];
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				for (int k = 0; k < d; k++) {
					if (exists[x][k])
						go[(k + dist[y] + 1) % d] = 1;
				}
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + ans[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 5, D = 50, M = N * D;
vector<int> g[M], rg[M];
bool a[N][D], used[M];
int comp[M];
vector<int> ord;
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(used, used + M, 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(used, used + M, 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 5, D = 50, M = N * D;
vector<int> g[M];
bool a[N][D], used[M];
int comp[M];
vector<int> ord;
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(used, used + M, 0);
	for (int i = 0; i < M; i++) {
		g[i].clear();
	}
	for (auto i : edges) {
		int v, u;
		tie(v, u) = i;
		g[u].pb(v);
	}
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
	}
	ord.clear();
	fill(used, used + M, 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 50, M = N * D;
vector<int> g[M], g1[M], rg[M];
bool a[N][D];
int comp[M];
vector<bool> used(M);
vector<int> ord;
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 51, M = N * D;
vector<int> g[M], g1[M], rg[M];
bool a[N][D];
vector<bool> used(M);
vector<int> ord, comp(M);
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	comp.clear();
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(0, 0));
	exists[0][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}
	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/
	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << '\n';
	}
}

void dfs4(int v, int c) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (comp[u] != c) continue;
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u, c);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));

/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i), i);
	}
	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		assert(dist[i] != INF);
	}
	for (int v = C - 1; v >= 0; v--) {
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				go[(dist[x] + dist[y] + 1) % d] = 1;
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + dp1[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(0, 0));
	exists[0][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}
	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/
	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << '\n';
	}
}

void dfs4(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
	// cout << v << ' ' << dist[v] << '\n';
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));

/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i));
	}
	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		assert(dist[i] != INF);
	}
	for (int v = C - 1; v >= 0; v--) {
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				go[(dist[x] + dist[y] + 1) % d] = 1;
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + dp1[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(root, 0));
	exists[root][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}

	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << ' ';
	}
	// cout << endl;
}

void dfs4(int v, int c) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (comp[u] != c) continue;
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u, c);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));
	// assert(sz(ord) == C);
/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i), i);
	}

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/

	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		assert(dist[i] != INF);
	}
	for (int it = C - 1; it >= 0; it--) {
		int v = ord[it];
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				for (int k = 0; k < d; k++) {
					if (exists[x][k])
						go[(k + dist[y] + 1) % d] = 1;
				}
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + ans[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << ans[i][j] << ' ';
		}
		cout << '\n';
	}*/
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 5, D = 50, M = N * D;
vector<int> g[M], rg[M];
bool a[N][D];
int comp[M];
vector<bool> used(M);
vector<int> ord;
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, INF = 1e9;
vector<int> g[N], rg[N];
vector<vector<int>> components;
map<int, vector<pair<int, int>>> g1[N];
vector<int> used(N), comp(N), ord;
int n, m, d;
int a[N][D], exists[N][D], dp1[N][D], ans[N][D], dist[N];
int C = 0;

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	components.back().pb(v);
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto i : g1[v]) {
		if (!used[i.fs])
			dfs3(i.fs);
	}
	ord.pb(v);
}

int get_root(int c) {
	assert(sz(components[c]));
	return components[c][0];
}

void bfs(int st) {
	int root = get_root(st);
	int c = comp[root];
	queue<pair<int, int>> q;
	q.push(MP(root, 0));
	exists[root][0] = 1;
	while (sz(q)) {
		int v, day;
		tie(v, day) = q.front();
		day = (day + 1) % d;
		q.pop();
		for (auto u : g[v]) {
			if (comp[u] != c || exists[u][day]) continue;
			exists[u][day] = 1;
			q.push(MP(u, day));
		}
	}

	for (int i = 0; i < d; i++) {
		for (auto v : components[st]) {
			bool can = 0;
			for (int j = 0; j < d && !can; j++) {
				can |= a[v][(i + j) % d] && exists[v][j];
			}
			dp1[c][i] += can;
		}
		// cout << dp1[c][i] << ' ';
	}
	// cout << endl;
}

void dfs4(int v, int c) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (comp[u] != c) continue;
		if (used[u] && dist[u] != INF) dist[v] = min(dist[v], dist[u] + 1);
		else if (!used[u]) {
			dfs4(u, c);
			dist[v] = min(dist[v], dist[u] + 1);
		}
	}
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	cin >> n >> m >> d;
	for (int i = 0; i < n; i++) dist[i] = INF;
	vector<pair<int, int>> edges(m);
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		edges[i] = {v, u};
		g[v].pb(u);
		rg[u].pb(v);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			dfs1(i);
		}
	}
	reverse(all(ord));
	fill(all(used), 0ll);
	for (auto v : ord) {
		if (!used[v]) {
			components.pb({});
			dfs2(v);
			C++;
		}
	}
	fill(all(used), 0ll);
	ord.clear();
	for (int i = 0; i < m; i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v], u = comp[u];
		if (v != u) {
			g1[v][u].pb(MP(edges[i].fs, edges[i].sc));
		}
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	fill(all(used), 0ll);
	reverse(all(ord));
	assert(sz(ord) == C);
/*	for (auto x : ord) {
		cout << x << ' ';
	}
	cout << '\n';*/

	for (int i = 0; i < C; i++) {
		sort(all(components[i]));
		bfs(i);
		dist[get_root(i)] = 0;
		dfs4(get_root(i), i);
	}

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << exists[i][j] << ' ';
		}
		cout << endl;
	}*/

	for (int i = 0; i < n; i++) {
		// cout << dist[i] << '\n';
		assert(dist[i] != INF);
	}
	for (int it = C - 1; it >= 0; it--) {
		int v = ord[it];
		for (int i = 0; i < d; i++) {
			ans[v][i] = dp1[v][i];
		}
		for (auto i : g1[v]) {
			int u = i.fs;
			vector<int> go(d);
			for (auto j : i.sc) {
				int x, y;
				tie(x, y) = j;
				for (int k = 0; k < d; k++) {
					if (exists[x][k])
						go[(k + dist[y] + 1) % d] = 1;
				}
			}
			for (int j = 0; j < d; j++) {
				for (int k = 0; k < d; k++) {
					if (go[k])
						ans[v][j] = max(ans[v][j], dp1[v][j] + ans[u][(j + k) % d]);
				}
			}
		}

	}
	int res = ans[comp[0]][0];
	cout << res << '\n';

	/*for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			cout << ans[i][j] << ' ';
		}
		cout << '\n';
	}*/
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 55, M = N * D;
vector<int> g[M], g1[M], rg[M];
int a[N][D], val[M], dp[M];
vector<int> used(M), ord, comp(M);
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}

	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) val[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		dp[v] = val[v];
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u] + val[v]);
		}
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

// #define int long long

#define fs first
#define sc second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define MP make_pair
#define pb push_back
#define sqr(x) ((x) * (x))
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 1e5 + 100, D = 51, M = N * D;
vector<int> g[M], g1[M], rg[M];
int a[N][D];
vector<int> used(M), ord, comp(M);
int n, m, d;
int C;

int get_hash(int x, int y) {
	return x * d + y;
}

void dfs1(int v) {
	used[v] = 1;
	for (auto u : g[v]) {
		if (!used[u]) {
			dfs1(u);
		}
	}
	ord.pb(v);
}

void dfs2(int v) {
	used[v] = 1;
	comp[v] = C;
	for (auto u : rg[v]) {
		if (!used[u]) {
			dfs2(u);
		}
	}
}

void dfs3(int v) {
	used[v] = 1;
	for (auto u : g1[v]) {
		if (!used[u]) {
			dfs3(u);
		}
	}
	ord.pb(v);
}

signed main() {
	fastio;
	#ifdef FlameDragon
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	vector<pair<int, int>> edges;
	auto add_edge = [&](int v, int u) {
		g[v].pb(u);
		rg[u].pb(v);
		edges.pb({v, u});
	};
	cin >> n >> m >> d;
	for (int i = 0; i < m; i++) {
		int v, u;
		cin >> v >> u;
		v--; u--;
		for (int j = 0; j < d; j++) {
			add_edge(get_hash(v, j), get_hash(u, (j + 1) % d));
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < d; j++) {
			char c;
			cin >> c;
			a[i][j] = c == '1';
		}
	}
	for (int i = 0; i < n * d; i++) {
		if (!used[i])
			dfs1(i);
	}
	reverse(all(ord));
	fill(all(used), 0);
	for (auto v : ord) {
		if (!used[v]) {
			dfs2(v);
			C++;
		}
	}
	for (int i = 0; i < n * d; i++) {
		g[i].clear();
		rg[i].clear();
	}
	ord.clear();
	fill(all(used), 0);
	for (int i = 0; i < sz(edges); i++) {
		int v, u;
		tie(v, u) = edges[i];
		v = comp[v];
		u = comp[u];
		if (v != u) {
			g1[v].pb(u);
		}
	}
	edges.clear();
	vector<int> dp(M);
	for (int v = 0; v < n; v++) {
		set<int> kek;
		for (int i = 0; i < d; i++) {
			if (a[v][i])
				kek.insert(comp[get_hash(v, i)]);
		}
		for (auto x : kek) dp[x]++;
	}
	for (int i = 0; i < C; i++) {
		if (!used[i]) {
			dfs3(i);
		}
	}
	reverse(all(ord));
	for (int v = C - 1; v >= 0; v--) {
		int cur = dp[v];
		dp[v] = 0;
		for (auto u : g1[v]) {
			dp[v] = max(dp[v], dp[u]);
		}
		dp[v] += cur;
	}
	cout << dp[comp[0]];
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 5000000 + 10;

vector<int> G[maxn], F[maxn];
int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
stack<int> S;

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u], lowlink[v]);
        } else if(!sccno[v]) {
            lowlink[u] = min(lowlink[u], pre[v]);
        }
    }
    if(lowlink[u] == pre[u]) {
        scc_cnt++;
        for(;;) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if(x == u)
                break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    memset(sccno, 0, sizeof(sccno));
    memset(pre, 0, sizeof(pre));
    for(int i = 0; i < n; i++)
        if(!pre[i])
            dfs(i);
}
bool vis[maxn];
int num[maxn], c[maxn];
int cal(int o) {
    if(c[o] != -1) return c[o];
    int tmp = 0;
    for(auto &i:F[o]) {
        tmp = max(tmp, cal(i));
    }
    return c[o] = tmp + num[o];
}
char open[maxn / 40][55];
int main() {
    int n, m, d;
    memset(c, -1, sizeof(c));
    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 i = 0; i < d; ++i) {
            G[u * d + i].push_back(v * d + (i + 1) % d);
        }
    }
    for(int i = 0; i < n; ++i) {
        scanf("%s", open[i]);
    }
    n *= d;
    find_scc(n);
    n /= d;
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < d; ++j) {
            if(vis[sccno[i * d + j]] == 0 && open[i][j] == '1') {
                vis[sccno[i * d + j]] = 1;
                num[sccno[i * d + j]] ++;
            }
        }
        for(int j = 0; j < d; ++j) {
            vis[sccno[i * d + j]] = 0;
        }
    }
    for(int i = 0; i < n * d; ++i) {
        for(auto &j: G[i]) {
            if(sccno[i] != sccno[j]) {
                F[sccno[i]].push_back(sccno[j]);
            }
        }
    }
    printf("%d\n", cal(sccno[0]));
    return 0;
}


//
// Created by mile on 2019/7/30.
//
//
#include <bits/stdc++.h>

using namespace std;
const int maxn = 5000050;

int dfs_clock, scc_cnt;
int dfn[maxn], low[maxn], sccno[maxn];
int num[maxn], c[maxn];
int head[maxn], edge[maxn], nxt[maxn], cnt;
bool vis[maxn];
vector<int> F[maxn];
int st[maxn], top;
char s[maxn/40][55];

void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    st[++top] = u;
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = edge[i];
        if(!dfn[v]) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(!sccno[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        ++scc_cnt;
        while(true) {
            int x = st[top--];
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
void find_bcc(int n) {
    dfs_clock = scc_cnt = top = 0;
    for(int i = 0; i < n; i++) {
        if(!dfn[i]) dfs(i);
    }
}

int cal(int s) {
    if(c[s] != -1) return c[s];
    int tmp = 0;
    for(auto &i : F[s]) {
        tmp = max(tmp, cal(i));
    }
    return c[s] = tmp+num[s];
}

void addedge(int u, int v){
    edge[cnt] = v;
    nxt[cnt] = head[u];
    head[u] = cnt++;
}

int main()
{
    int n, m, d;
    memset(c, -1, sizeof(c));
    memset(head, -1, sizeof(head));
    cnt = 0;
    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++) {
            addedge(u*d+j, v*d+(j+1)%d);
        }
    }
    for(int i = 0; i < n; i++) scanf("%s", s[i]);
    find_bcc(n*d);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < d; j++) {
            if(s[i][j] == '1' && !vis[sccno[i*d+j]]) {
                num[sccno[i*d+j]]++;
                vis[sccno[i*d+j]] = true;
            }
        }
        for(int j = 0; j < d; j++) {
            vis[sccno[i*d+j]] = false;
        }
    }
    for(int i = 0; i < n*d; i++) {
        for(int j = head[i]; ~j; j = nxt[j]) {
            if(j >= maxn || j < 0) break;
            int x = edge[j];
            if(sccno[i] != sccno[x]) {
                F[sccno[i]].push_back(sccno[x]);
            }
        }
    }
    printf("%d\n", cal(sccno[0]));
    return 0;
}


//
// Created by mile on 2019/7/30.
//
//
#include <bits/stdc++.h>

using namespace std;
const int maxn = 5000006;

int n, m, d;
int dfs_clock, scc_cnt;
int dfn[maxn], low[maxn], sccno[maxn];
int num[maxn], c[maxn];
bool vis[maxn];
vector<int> G[maxn], F[maxn];
stack<int> st;
char s[maxn/40][52];

void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    st.push(u);
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(!dfn[v]) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(!sccno[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        ++scc_cnt;
        while(true) {
            int x = st.top(); st.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}

int cal(int s) {
    if(c[s] != -1) return c[s];
    int tmp = 0;
    for(auto &i : F[s]) {
        tmp = max(tmp, cal(i));
    }
    return c[s] = tmp+num[s];
}

int main()
{
    memset(c, -1, sizeof(c));
    scanf("%d%d%d", &n, &m, &d);
    for(int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        u--, v--;
        for(int j = 0; j < d; j++) {
            G[u*d+j].push_back(v*d+(j+1)%d);
        }
    }
    for(int i = 1; i <= n; i++) scanf("%s", s[i]);
    for(int i = 0; i < n*d; i++) {
        if(!dfn[i]) dfs(i);
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j < d; j++) {
            if(s[i][j] == '1' && !vis[sccno[(i-1)*d+j]]) {
                num[sccno[(i-1)*d+j]]++;
                vis[sccno[(i-1)*d+j]] = true;
            }
        }
        for(int j = 0; j <= d; j++) {
            vis[sccno[(i-1)*d+j]] = false;
        }
    }
    for(int i = 0; i < n*d; i++) {
        for(auto j : G[i]) {
            if(sccno[i] != sccno[j]) {
                F[sccno[i]].push_back(sccno[j]);
            }
        }
    }
    printf("%d\n", cal(sccno[0]));
    return 0;
}


//
// Created by mile on 2019/7/30.
//
//
#include <bits/stdc++.h>

using namespace std;
const int maxn = 5000010;

int dfs_clock, scc_cnt;
int dfn[maxn], low[maxn], sccno[maxn];
int num[maxn], c[maxn];
int head[maxn], edge[maxn], nxt[maxn], cnt;
bool vis[maxn];
vector<int> F[maxn];
stack<int> st;
char s[maxn/40][55];

void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    st.push(u);
    for(int i = head[u]; i; i = nxt[i]) {
        int v = edge[i];
        if(!dfn[v]) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(!sccno[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        ++scc_cnt;
        while(true) {
            int x = st.top(); st.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
void find_bcc(int n) {
    dfs_clock = scc_cnt = 0;
    memset(sccno, 0, sizeof(sccno));
    memset(dfn, 0, sizeof(dfn));
    for(int i = 0; i < n; i++) {
        if(!dfn[i]) dfs(i);
    }
}

int cal(int s) {
    if(c[s] != -1) return c[s];
    int tmp = 0;
    for(auto &i : F[s]) {
        tmp = max(tmp, cal(i));
    }
    return c[s] = tmp+num[s];
}

void addedge(int u, int v){
    edge[++cnt] = v;
    nxt[cnt] = head[u];
    head[u] = cnt;
}

int main()
{
    int n, m, d;
    memset(c, -1, sizeof(c));
    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++) {
            addedge(u*d+j, v*d+(j+1)%d);
        }
    }
    for(int i = 0; i < n; i++) scanf("%s", s[i]);
    find_bcc(n*d);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < d; j++) {
            if(s[i][j] == '1' && !vis[sccno[i*d+j]]) {
                num[sccno[i*d+j]]++;
                vis[sccno[i*d+j]] = true;
            }
        }
        for(int j = 0; j < d; j++) {
            vis[sccno[i*d+j]] = false;
        }
    }
    for(int i = 0; i < n*d; i++) {
        for(int j = head[i]; j; j = nxt[j]) {
            int x = edge[j];
            if(sccno[i] != sccno[x]) {
                F[sccno[i]].push_back(sccno[x]);
            }
        }
    }
    printf("%d\n", cal(sccno[0]));
    return 0;
}