#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;
}
