1138_E. Museums Tour_21596
In the country N, there are n cities connected by m one-way roads. Although this country seems unremarkable, there are two interesting facts about it. At first, a week lasts d days here. At second, there is exactly one museum in each city of the country N.

Travel agency "Open museums" is developing a new program for tourists interested in museums. Agency's employees know which days each of the museums is open. The tour should start in the capital — the city number 1, and the first day of the tour must be on the first day of a week. Each day a tourist will be in some city, watching the exposition in its museum (in case museum is open today), and by the end of the day, the tour either ends or the tourist goes into another city connected by a road with the current one. The road system of N is designed in such a way that traveling by a road always takes one night and also all the roads are one-way. It's allowed to visit a city multiple times during the trip.

You should develop such route for the trip that the number of distinct museums, possible to visit during it, is maximum.

Input

The first line contains three integers n, m and d (1 ≤ n ≤ 100 000, 0 ≤ m ≤ 100 000, 1 ≤ d ≤ 50), the number of cities, the number of roads and the number of days in a week.

Each of next m lines contains two integers u_i and v_i (1 ≤ u_i, v_i ≤ n, u_i ≠ v_i), denoting a one-way road from the city u_i to the city v_i.

The next n lines contain the museums' schedule. The schedule of the museum located in the i-th city is described in the i-th of these lines. Each line consists of exactly d characters "0" or "1", the j-th character of the string equals to "1" if the museum is open at the j-th day of a week, and "0", otherwise.

It's guaranteed that for each pair of cities (u, v) there exists no more than one road leading from u to v.

Output

Print a single integer — the maximum number of distinct museums, that it's possible to visit, starting a trip in the first city on the first day of the week.

Examples

Input


4 5 3
3 1
1 2
2 4
4 1
2 3
011
110
111
001


Output


3


Input


3 3 7
1 2
1 3
2 3
1111111
0000000
0111111


Output


2

Note

Explanation of the first example <image>

The maximum number of distinct museums to visit is 3. It's possible to visit 3 museums, for example, in the way described below.

  * Day 1. Now it's the 1st day of a week, and the tourist is in the city 1. The museum there is closed. At night the tourist goes to the city number 2. 
  * Day 2. Now it's the 2nd day of a week, and the tourist is in the city 2. The museum there is open, and the tourist visits it. At night the tourist goes to the city number 4. 
  * Day 3. Now it's the 3rd day of a week, and the tourist is in the city 4. The museum there is open, and the tourist visits it. At night the tourist goes to the city number 1. 
  * Day 4. Now it's the 1st day of a week, and the tourist is in the city 1. The museum there is closed. At night the tourist goes to the city number 2. 
  * Day 5. Now it's the 2nd of a week number 2, and the tourist is in the city 2. The museum there is open, but the tourist has already visited it. At night the tourist goes to the city number 3. 
  * Day 6. Now it's the 3rd day of a week, and the tourist is in the city 3. The museum there is open, and the tourist visits it. After this, the tour is over. 

Explanation of the second example <image>

The maximum number of distinct museums to visit is 2. It's possible to visit 2 museums, for example, in the way described below.

  * Day 1. Now it's the 1st day of a week, and the tourist is in the city 1. The museum there is open, and the tourist visits it. At night the tourist goes to the city number 2. 
  * Day 2. Now it's the 2nd day of a week, and the tourist is in the city 2. The museum there is closed. At night the tourist goes to the city number 3. 
  * Day 3. Now it's the 3rd day of a week, and the tourist is in the city 3. The museum there is open, and the tourist visits it. After this, the tour is over. 
import java.io.*;
import java.math.*;
import java.util.*;
import java.util.stream.*;

public class C {

	int[][] g;
	int[][] gr;

	int[] mark;

	void submit() {
		int n = nextInt();
		int m = nextInt();

		int d = nextInt();
		int[] deg = new int[n];
		int[] degr = new int[n];

		int[] a = new int[2 * m];

		for (int i = 0; i < m; i++) {
			a[2 * i] = nextInt() - 1;
			a[2 * i + 1] = nextInt() - 1;
			deg[a[2 * i]]++;
			degr[a[2 * i + 1]]++;
		}

		g = new int[n][];
		gr = new int[n][];
		mark = new int[n];

		for (int i = 0; i < n; i++) {
			g[i] = new int[deg[i]];
			gr[i] = new int[degr[i]];
		}

		Arrays.fill(deg, 0);
		Arrays.fill(degr, 0);

		for (int i = 0; i < 2 * m; i += 2) {
			int v = a[i];
			int u = a[i + 1];
			g[v][deg[v]++] = u;
			gr[u][degr[u]++] = v;
		}

		Arrays.fill(mark, -1);
		dfs0(0, 0);

		ptr = n;
		comp = new int[n];
		order = new int[n];
		compSz = new int[n];

		for (int i = 0; i < n; i++) {
			if (comp[i] == 0) {
				dfs1(i);
			}
		}
		ptr = 0;
		for (int v : order) {
			if (comp[v] == -1) {
				dfs2(v);
				ptr++;
			}
		}

		// System.err.println(Arrays.toString(comp));
		// System.err.println(Arrays.toString(compSz));

		int[] pers = new int[ptr];
		Arrays.fill(pers, d);

		for (int v = 0; v < n; v++) {
			for (int u : g[v]) {
				if (comp[v] != comp[u]) {
					continue;
				}
				int delta = Math.abs(mark[v] + 1 - mark[u]);
				pers[comp[v]] = gcd(pers[comp[v]], delta);
			}
		}

		int[][] who = new int[ptr][];
		for (int i = 0; i < ptr; i++) {
			who[i] = new int[compSz[i]];
		}

		for (int i = 0; i < n; i++) {
			int idx = comp[i];
			who[idx][--compSz[idx]] = i;
		}
		
		makeZeroFirst(who[comp[0]]);

		int[][] dp = new int[ptr][d];

		int[][] sch = new int[n][d];
		for (int i = 0; i < n; i++) {
			String s = nextToken();

			for (int j = 0; j < d; j++) {
				sch[i][j] = s.charAt(j) - '0';
			}
		}

		int[] shifts = new int[n];

		for (int v = 0; v < n; v++) {
			int shift = (mark[v] - mark[who[comp[v]][0]]) % pers[comp[v]];
			if (shift < 0) {
				shift += pers[comp[v]];
			}
			shifts[v] = shift;
		}

		for (int i = ptr - 1; i >= 0; i--) {
			int[] vs = who[i];
			int per = pers[i];

			int[] profit = new int[per];

			for (int v : vs) {
				int shift = shifts[v];

//				for (int j = 0; j < d; j++) {
//					if (sch[v][j] == 0) {
//						continue;
//					}
//					int idx = j % per;
//					idx -= shift;
//					if (idx < 0) {
//						idx += per;
//					}
//
//					profit[idx]++;
//				}
				
				for (int idx = 0; idx < per; idx++) {
					int j = (idx + shift) % per;
					int val = 0;
					for (int k = j; k < d; k += per) {
						val |= sch[v][k];
					}
					profit[idx] += val;
				}
			}

			int[] dpRow = dp[i];
			for (int j = 0; j < d; j++) {
				dpRow[j] = profit[j % per];
			}

			for (int v : vs) {
				int shift = shifts[v];

				for (int u : g[v]) {
					if (comp[u] == comp[v]) {
						continue;
					}
					if (comp[u] < comp[v]) {
						throw new AssertionError();
					}

					for (int j = 0; j < d; j++) {
						
						for (int z = 0; z < d / per; z++) {
						
						int jj = (j + shift + z * per + 1 - shifts[u]) % d;
						if (jj < 0) {
							jj += d;
						}
						
						dpRow[j] = Math.max(dpRow[j], profit[j % per]
								+ dp[comp[u]][jj]);
						}
					}
				}
			}
			
//			System.err.println(Arrays.toString(who[i]) + " " + Arrays.toString(dp[i]));
		}
		
		out.println(dp[comp[0]][0]);
	}
	
	void makeZeroFirst(int[] a) {
		int idx = 0;
		while (a[idx] != 0) {
			idx++;
		}
		a[idx] = a[0];
		a[0] = 0;
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	int[] order;
	int ptr;
	int[] comp;
	int[] compSz;

	void dfs1(int v) {
		comp[v] = -1;
		for (int u : g[v]) {
			if (comp[u] == 0) {
				dfs1(u);
			}
		}
		order[--ptr] = v;
	}

	void dfs2(int v) {
		comp[v] = ptr;
		compSz[ptr]++;
		for (int u : gr[v]) {
			if (comp[u] == -1) {
				dfs2(u);
			}
		}
	}

	void dfs0(int v, int c) {
		mark[v] = c;
		for (int u : g[v]) {
			if (mark[u] == -1) {
				dfs0(u, c + 1);
			}
		}
	}

	void test() {

	}

	void stress() {
		for (int tst = 0;; tst++) {
			if (false) {
				throw new AssertionError();
			}
			System.err.println(tst);
		}
	}

	C() throws IOException {
		is = System.in;
		out = new PrintWriter(System.out);
		submit();
		// stress();
		// test();
		out.close();
	}

	static final Random rng = new Random();
	static final int C = 5;

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

	public static void main(String[] args) throws IOException {
		new C();
	}

	private InputStream is;
	PrintWriter out;

	private byte[] buf = new byte[1 << 14];
	private int bufSz = 0, bufPtr = 0;

	private int readByte() {
		if (bufSz == -1)
			throw new RuntimeException("Reading past EOF");
		if (bufPtr >= bufSz) {
			bufPtr = 0;
			try {
				bufSz = is.read(buf);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			if (bufSz <= 0)
				return -1;
		}
		return buf[bufPtr++];
	}

	private boolean isTrash(int c) {
		return c < 33 || c > 126;
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isTrash(b))
			;
		return b;
	}

	String nextToken() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	String nextString() {
		int b = readByte();
		StringBuilder sb = new StringBuilder();
		while (!isTrash(b) || b == ' ') {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	double nextDouble() {
		return Double.parseDouble(nextToken());
	}

	char nextChar() {
		return (char) skip();
	}

	int nextInt() {
		int ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}

	long nextLong() {
		long ret = 0;
		int b = skip();
		if (b != '-' && (b < '0' || b > '9')) {
			throw new InputMismatchException();
		}
		boolean neg = false;
		if (b == '-') {
			neg = true;
			b = readByte();
		}
		while (true) {
			if (b >= '0' && b <= '9') {
				ret = ret * 10 + (b - '0');
			} else {
				if (b != -1 && !isTrash(b)) {
					throw new InputMismatchException();
				}
				return neg ? -ret : ret;
			}
			b = readByte();
		}
	}
}
