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 CPP):

Solution:
#include <bits/stdc++.h>
int V, E, P;
std::vector<std::pair<int, int>> door;
std::vector<int> edge[1005];
std::bitset<1005> visited[2];
int ind[1005][1005];
int parent[2][1005];
int rank[2][1005];
std::vector<int> locked[2][1005];
std::vector<int> vkeys[2][1005];
std::bitset<1005> keys[2][1005];
int findRoot(int crt, int node) {
  if (parent[crt][node] == node) return node;
  return (parent[crt][node] = findRoot(crt, parent[crt][node]));
}
void unionSets(int crt, int node1, int node2, std::queue<int>& q) {
  node1 = findRoot(crt, node1);
  node2 = findRoot(crt, node2);
  for (int i : locked[crt][node2]) {
    if (keys[crt][node1][i] == true) {
      int n1 = door[i].first;
      int n2 = door[i].second;
      if (findRoot(crt, n2) == node2) std::swap(n1, n2);
      q.push(n1);
    }
  }
  for (int i : locked[crt][node1]) {
    if (keys[crt][node2][i] == true) {
      int n1 = door[i].first;
      int n2 = door[i].second;
      if (findRoot(crt, n2) == node1) std::swap(n1, n2);
      q.push(n1);
    }
  }
  if (rank[crt][node1] < rank[crt][node2]) std::swap(node1, node2);
  if (rank[crt][node1] == rank[crt][node2]) rank[crt][node1]++;
  for (int i : locked[crt][node2]) locked[crt][node1].push_back(i);
  for (int i : vkeys[crt][node2]) {
    vkeys[crt][node1].push_back(i);
    keys[crt][node1][i] = true;
  }
  parent[crt][node2] = node1;
}
void traverse(int crt, int node) {
  int root = node, key, newNode = true;
  std::queue<int> q;
  std::queue<int> check;
  q.push(node);
  while (q.empty() == false) {
    node = q.front();
    root = findRoot(crt, node);
    q.pop();
    visited[crt][node] = true;
    for (int next : edge[node]) {
      key = ind[node][next];
      root = findRoot(crt, node);
      if (keys[crt][root][key] == true) {
        if (visited[crt][next] == false) {
          visited[crt][next] = true;
          q.push(next);
          unionSets(crt, node, next, q);
        } else if (findRoot(crt, node) != findRoot(crt, next)) {
          unionSets(crt, node, next, q);
        }
      } else
        locked[crt][findRoot(crt, node)].push_back(key);
    }
  }
}
void solve(int crt) {
  for (int node = 1; node <= V; node++) {
    rank[crt][node] = 1;
    parent[crt][node] = node;
  }
  for (int node = 1; node <= V; node++) {
    if (visited[crt][node] == false) {
      traverse(crt, node);
    }
  }
}
std::unordered_map<std::string, int> person;
std::unordered_map<int, int> keyLocation;
void print() {
  std::string s;
  bool valid = true;
  int crt = 1;
  for (int i = 0, node, k, key; i < P; i++) {
    std::cin >> s >> node >> k;
    if (findRoot(0, node) != findRoot(0, person[s])) valid = false;
    for (int j = 0; j < k; j++) {
      std::cin >> key;
      if (findRoot(0, node) != findRoot(0, keyLocation[key])) valid = false;
      vkeys[crt][node].push_back(key);
      keys[crt][node][key] = true;
    }
  }
  solve(crt);
  for (int i = 1; i <= V; i++) {
    if (findRoot(1, findRoot(0, i)) != findRoot(1, i) or
        findRoot(0, findRoot(1, i)) != findRoot(0, i))
      valid = false;
  }
  if (valid == true)
    std::cout << "YES";
  else
    std::cout << "NO";
}
int32_t main() {
  std::cin >> V >> E >> P;
  door.resize(E + 1);
  for (int i = 0, src, dest; i < E; i++) {
    std::cin >> src >> dest;
    door[i + 1] = {src, dest};
    edge[src].push_back(dest);
    edge[dest].push_back(src);
    ind[src][dest] = i + 1;
    ind[dest][src] = i + 1;
  }
  std::string s;
  int crt = 0;
  for (int i = 0, node, k, key; i < P; i++) {
    std::cin >> s >> node >> k;
    person[s] = node;
    for (int j = 0; j < k; j++) {
      std::cin >> key;
      keyLocation[key] = node;
      vkeys[crt][node].push_back(key);
      keys[crt][node][key] = true;
    }
  }
  solve(crt);
  print();
  return 0;
}