import java.io.*;
import java.util.*;
import java.math.*;

public class railroads_aa {
	public static void main(String[] args) {
		new railroads_aa().run();
	}

	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	boolean eof = false;

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			br = new BufferedReader(new FileReader(FNAME + ".in"));
			out = new PrintWriter(FNAME + ".out");
			solve();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(566);
		}
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return "0";
			}
		}
		return st.nextToken();
	}

	int nextInt() {
		return Integer.parseInt(nextToken());
	}

	void myAssert(boolean u, String message) {
		if (!u) {
			throw new Error("Assertion failed!!! " + message);
		}
	}

	int inBounds(int x, int l, int r, String name) {
		myAssert(l <= x && x <= r, name + " is not in bounds: " + x
				+ " not in [" + l + ", " + r + "]");
		return x;
	}

	String FNAME = "railroads";

	int MAXA = 1000000000;

	class DisjointSet {
		public DisjointSet(int n) {
			u = new int[n];
			for (int i = 0; i < u.length; i++) {
				u[i] = i;
			}
			comp = n;
		}

		int comp;

		int[] u;

		public void union(int x, int y) {
			x = get(x);
			y = get(y);
			if (x != y) {
				u[x] = y;
				comp--;
			}
		}

		private int get(int x) {
			if (u[x] != x) {
				u[x] = get(u[x]);
			}
			return u[x];
		}

	}

	private void solve() throws IOException {
		int n = inBounds(nextInt(), 1, 100, "n");
		int m = inBounds(nextInt(), 0, 5000, "m");
		int k = inBounds(nextInt(), 1, 10, "k");
		DisjointSet ds = new DisjointSet(n);
		for (int i = 0; i < m; i++) {
			int x = inBounds(nextInt(), 1, n, "x_" + (i + 1)) - 1;
			int y = inBounds(nextInt(), 1, n, "y_" + (i + 1)) - 1;
			ds.union(x, y);
		}
		long[][] prod = new long[ds.comp][k];
		long[][][] conv = new long[ds.comp][k][k];
		long[][] uses = new long[ds.comp][k];
		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		int s = 0;
		for (int i = 0; i < n; i++) {
			int x = ds.get(i);
			if (!hm.containsKey(x)) {
				hm.put(x, hm.size());
			}
			x = hm.get(x);
			int r = nextInt();
			s += r;
			for (int j = 0; j < r; j++) {
				int res = inBounds(nextInt(), 1, k, "g_{" + (i + 1) + ", r_"
						+ (j + 1) + "}") - 1;
				int a = inBounds(nextInt(), 1, MAXA, "a_{" + (i + 1) + ", r_"
						+ (j + 1) + "}");
				prod[x][res] += a;

			}
			int p = nextInt();
			s += p;
			for (int j = 0; j < p; j++) {
				int res1 = inBounds(nextInt(), 1, k, "g1_{" + (i + 1) + ", p_"
						+ (j + 1) + "}") - 1;
				int res2 = inBounds(nextInt(), 1, k, "g2_{" + (i + 1) + ", p_"
						+ (j + 1) + "}") - 1;
				int a = inBounds(nextInt(), 1, MAXA, "a_{" + (i + 1) + ", p_"
						+ (j + 1) + "}");
				conv[x][res1][res2] += a;
			}
			int c = nextInt();
			s += c;
			for (int j = 0; j < c; j++) {
				int res = inBounds(nextInt(), 1, k, "g_{" + (i + 1) + ", c_"
						+ (j + 1) + "}") - 1;
				int a = inBounds(nextInt(), 1, MAXA, "a_{" + (i + 1) + ", c_"
						+ (j + 1) + "}");
				uses[x][res] += a;
			}
		}
		myAssert(s <= 50000, "Sum is too big. " + s);
		long ans = 0;
		for (int i = 0; i < uses.length; i++) {
			Graph g = new Graph(ds.comp * 2 * k + 2);
			int first = 1;
			int second = 1 + k;
			for (int j = 0; j < prod[i].length; j++) {
				g.addEdge(0, first + j, prod[i][j]);
			}
			for (int j = 0; j < uses[i].length; j++) {
				g.addEdge(second + j, 2 * k + 1, uses[i][j]);
			}
			for (int j = 0; j < conv[i].length; j++) {
				for (int q = 0; q < conv[i][j].length; q++) {
					g.addEdge(first + j, second + q, conv[i][j][q]);
				}
			}
			for (int j = 0; j < k; j++) {
				g.addEdge(first + j, second + j, Long.MAX_VALUE / 2);
			}
			ans += g.maxFlow(0, 2 * k + 1);
		}
		out.println(ans);
	}

	class Graph {
		public Graph(int n) {
			ver = new Vertex[n];
			for (int i = 0; i < ver.length; i++) {
				ver[i] = new Vertex(i);
			}
		}

		public long maxFlow(int s, int t) {
			long flow = 0;
			for (long mask = 1L << 60; mask > 0; mask >>= 1) {
				for (Vertex v : ver) {
					v.u = false;
				}
				while (dfs(ver[s], ver[t], mask)) {
					flow += mask;
					for (Vertex v : ver) {
						v.u = false;
					}
				}
			}
			return flow;
		}

		private boolean dfs(Vertex x, Vertex t, long mask) {
			if (x.n == t.n) {
				return true;
			}
			x.u = true;
			for (Edge e : x.edges) {
				if ((e.c - e.f) >= mask && !e.y.u && dfs(e.y, t, mask)) {
					e.f += mask;
					e.r.f -= mask;
					return true;
				}
			}
			return false;
		}

		public void addEdge(int i, int j, long c) {
			Edge e = new Edge(ver[i], ver[j], c);
			Edge er = new Edge(ver[j], ver[i], 0);
			e.r = er;
			er.r = e;
			ver[i].edges.add(e);
			ver[j].edges.add(er);
		}

		Vertex[] ver;
	}

	class Vertex {
		public Vertex(int i) {
			n = i;
			edges = new ArrayList<Edge>();
		}

		int n;
		boolean u;
		ArrayList<Edge> edges;
	}

	class Edge {
		public Edge(Vertex v1, Vertex v2, long c2) {
			x = v1;
			y = v2;
			c = c2;
		}

		Vertex x, y;
		long c;
		long f;
		Edge r;
	}
}
