Problem: Today you are to solve the problem even the famous Hercule Poirot can't cope with! That's why this crime has not yet been solved and this story was never included in Agatha Christie's detective story books. 

You are not informed on what crime was committed, when and where the corpse was found and other details. We only know that the crime was committed in a house that has n rooms and m doors between the pairs of rooms. The house residents are very suspicious, that's why all the doors can be locked with keys and all the keys are different. According to the provided evidence on Thursday night all the doors in the house were locked, and it is known in what rooms were the residents, and what kind of keys had any one of them. The same is known for the Friday night, when all the doors were also locked. On Friday it was raining heavily, that's why nobody left the house and nobody entered it. During the day the house residents could

  * open and close doors to the neighboring rooms using the keys at their disposal (every door can be opened and closed from each side); 
  * move freely from a room to a room if a corresponding door is open; 
  * give keys to one another, being in one room. 



"Little grey matter" of Hercule Poirot are not capable of coping with such amount of information. Find out if the positions of people and keys on the Thursday night could result in the positions on Friday night, otherwise somebody among the witnesses is surely lying.

Input

The first line contains three preset integers n, m и k (1 ≤ n, m, k ≤ 1000) — the number of rooms, the number of doors and the number of house residents respectively. The next m lines contain pairs of room numbers which join the doors. The rooms are numbered with integers from 1 to n. There cannot be more that one door between the pair of rooms. No door connects a room with itself. The next k lines describe the residents' position on the first night. Every line contains a resident's name (a non-empty line consisting of no more than 10 Latin letters), then after a space follows the room number, then, after a space — the number of keys the resident has. Then follow written space-separated numbers of the doors that can be unlocked by these keys. The doors are numbered with integers from 1 to m in the order in which they are described in the input data. All the residents have different names, uppercase and lowercase letters considered to be different. Every m keys occurs exactly once in the description. Multiple people may be present in one room, some rooms may be empty. The next k lines describe the position of the residents on the second night in the very same format. It is guaranteed that in the second night's description the residents' names remain the same and every m keys occurs exactly once.

Output

Print "YES" (without quotes) if the second arrangement can result from the first one, otherwise, print "NO".

Examples

Input

2 1 2
1 2
Dmitry 1 1 1
Natalia 2 0
Natalia 1 1 1
Dmitry 2 0


Output

YES


Input

4 4 3
1 3
1 2
2 3
3 4
Artem 1 1 4
Dmitry 1 1 2
Edvard 4 2 1 3
Artem 2 0
Dmitry 1 0
Edvard 4 4 1 2 3 4


Output

NO

Solution (in JAVA):

Solution:
import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.fill;
import static java.util.Arrays.binarySearch;
import static java.util.Arrays.sort;

public class Main {
	public static void main(String[] args) throws IOException {
		new Thread(null, new Runnable() {
			public void run() {
				try {
					try {
						if (new File("input.txt").exists())
							System.setIn(new FileInputStream("input.txt"));
					} catch (SecurityException e) {}
					new Main().run();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, "1", 1L << 24).start(); 
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");
	
	int N;
	int M;
	int K;

	MultiList graph;
	Map<String, Integer> map = new HashMap<String, Integer>();
	String[] names;
	
	int[] pos1;
	int[] pos2;
	int[] kpos1;
	int[] kpos2;
	int[][] keys1;
	int[][] keys2;
	
	void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		
		N = nextInt();
		M = nextInt();
		K = nextInt();
		
		graph = new MultiList(N, 4 * M + 10);
		
		for (int i = 0; i < M; i++) {
			int u = nextInt() - 1;
			int v = nextInt() - 1;
			graph.add(u, v, i);
			graph.add(v, u, i);
		}
		
		names = new String [2 * K];
		kpos1 = new int [2 * M];
		pos1 = new int [2 * K];
		keys1 = new int [2 * K][];
		
		for (int i = 0; i < K; i++) {
			map.put(names[i] = nextToken(), i);
			pos1[i] = nextInt() - 1;
			int kNum = nextInt();
			keys1[i] = new int [kNum];
			for (int j = 0; j < kNum; j++) {
				keys1[i][j] = nextInt() - 1;
				kpos1[keys1[i][j]] = pos1[i];
			}
		}
		
		kpos2 = new int [2 * M];
		pos2 = new int [2 * K];
		keys2 = new int [2 * K][];
		for (int i = 0; i < K; i++) {
			int ind = map.get(nextToken());
			pos2[ind] = nextInt() - 1;
			int kNum = nextInt();
			keys2[ind] = new int [kNum];
			for (int j = 0; j < kNum; j++) {
				keys2[ind][j] = nextInt() - 1;
				kpos2[keys2[ind][j]] = pos2[ind];
			}
		}
		
		DSF dsf1 = proc(pos1, keys1);
		DSF dsf2 = proc(pos2, keys2);
		
//		boolean ok = true;
		boolean ok = match(dsf1, dsf2) && match(dsf2, dsf1);
		
		for (int i = 0; i < M; i++) {
			if (!dsf1.sameSet(kpos1[i], kpos2[i]))
				ok = false;
			if (!dsf2.sameSet(kpos1[i], kpos2[i]))
				ok = false;
		}
		
		for (int i = 0; i < K; i++) {
			if (!dsf1.sameSet(pos1[i], pos2[i]))
				ok = false;
			if (!dsf2.sameSet(pos1[i], pos2[i]))
				ok = false;
		}
		
		out.println(ok ? "YES" : "NO");
	
		out.close();
	}
	
	boolean match(DSF dsf1, DSF dsf2) {
		for (int i = 0; i < N; i++)
			for (int j = i + 1; j < N; j++)
				if (dsf1.sameSet(i, j) && !dsf2.sameSet(i, j))
					return false;
		return true;
	}

	DSF proc(int[] pos, int[][] keys) {
		DSF dsf = new DSF(N);
		Set<Integer>[] ks = new Set [N];
		for (int i = 0; i < N; i++)
			ks[i] = new HashSet<Integer>();
		for (int i = 0; i < K; i++)
			for (int j = 0; j < keys[i].length; j++)
				ks[pos[i]].add(keys[i][j]);
		for (int it = 0; it <= N; it++) {
			for (int v = 0; v < N; v++) {
				for (int i = graph.head[v]; i != 0; i = graph.next[i]) {
					int setv = dsf.set(v);
					int setn = dsf.set(graph.vert[i]);
					if (ks[setv].contains(graph.door[i])) {
						if (dsf.union(v, graph.vert[i])) {
//							System.out.println(v + " " + graph.vert[i]);
							int c = dsf.set(v);
							if (c != setv)
								ks[c].addAll(ks[setv]);
							if (c != setn)
								ks[c].addAll(ks[setn]);
						}
					}
				}
			}
		}
		return dsf;
	}

	class DSF {
		int[] set;
		int[] rnk;
		
		DSF(int sz) {
			set = new int [2 * sz];
			rnk = new int [2 * sz];
			for (int i = 0; i < 2 * sz; i++)
				set[i] = i;
		}
		
		int set(int x) {
			return x == set[x] ? x : (set[x] = set(set[x]));
		}
		
		boolean union(int x, int y) {
			x = set(x);
			y = set(y);
			if (x == y)
				return false;
			if (rnk[x] > rnk[y]) {
				set[y] = x;
			} else {
				set[x] = y;
				if (rnk[x] == rnk[y])
					rnk[y]++;
			}
			return true;
		}
		
		boolean sameSet(int x, int y) {
			return set(x) == set(y);
		}
	}
	
	class MultiList {
		int[] head;
		int[] next;
		int[] vert;
		int[] door;
		int cnt = 1;
		
		MultiList(int vNum, int eNum) {
			head = new int [vNum];
			next = new int [eNum + 1];
			vert = new int [eNum + 1];
			door = new int [eNum + 1];
		}
		
		void add(int u, int v, int k) {
			next[cnt] = head[u];
			vert[cnt] = v;
			door[cnt] = k;
			head[u] = cnt++;
		}
	}
	
	String nextToken() throws IOException {
		while (!st.hasMoreTokens()) {
			st = new StringTokenizer(in.readLine());
		}
		
		return st.nextToken();
	}
	
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	
	String nextLine() throws IOException {
		st = new StringTokenizer("");
		return in.readLine();
	}
	
	boolean EOF() throws IOException {
		while (!st.hasMoreTokens()) {
			String s = in.readLine();
			
			if (s == null) {
				return true;
			}
			
			st = new StringTokenizer(s);
		}
		
		return false;
	}
}