#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int N, M, K;
pair<int, int> edge[MAXN];
struct component {
  multiset<string> people;
  multiset<int> key;
  inline void init() {
    people.clear();
    key.clear();
  }
  void merge(component &o) {
    for (__typeof(o.people.begin()) it = o.people.begin(); it != o.people.end();
         it++) {
      people.insert(*it);
    }
    for (__typeof(o.key.begin()) it = o.key.begin(); it != o.key.end(); it++) {
      key.insert(*it);
    }
    o.people.clear();
    o.key.clear();
  }
};
struct state {
  component room[MAXN];
  int parent[MAXN], rank[MAXN];
  bool opened[MAXN];
  inline void init() {
    for (int i = 0; i < N; i++) {
      room[i].init();
      parent[i] = i;
      rank[i] = 0;
    }
    for (int j = 0; j < M; j++) {
      opened[j] = false;
    }
  }
  inline int boss(int v) {
    return (v == parent[v] ? v : parent[v] = boss(parent[v]));
  }
  inline void unite(int u, int v) {
    u = boss(u);
    v = boss(v);
    if (u != v) {
      if (rank[u] > rank[v]) {
        parent[v] = u;
        room[u].merge(room[v]);
      } else {
        parent[u] = v;
        room[v].merge(room[u]);
        if (rank[u] == rank[v]) rank[v]++;
      }
    }
  }
  inline bool canOpen(int d) {
    int u = boss(edge[d].first), v = boss(edge[d].second);
    if (room[u].key.count(d) || room[v].key.count(d)) {
      unite(u, v);
      return true;
    }
    return false;
  }
  inline void process() {
    for (int i = 0; i < K; i++) {
      string str;
      cin >> str;
      int roomnum, len;
      scanf("%d %d", &roomnum, &len);
      roomnum--;
      room[roomnum].people.insert(str);
      for (int a, j = 0; j < len; j++) {
        scanf("%d", &a);
        room[roomnum].key.insert(a - 1);
      }
    }
    while (1) {
      bool done = true;
      for (int j = 0; j < M; j++) {
        if (!opened[j]) {
          if (canOpen(j)) {
            opened[j] = true;
            done = false;
          }
        }
      }
      if (done) {
        break;
      }
    }
  }
} start, finish;
template <class T>
bool set_eq(multiset<T> a, multiset<T> b) {
  if ((int)a.size() != (int)b.size()) return false;
  __typeof(b.begin()) it2 = b.begin();
  for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++) {
    if ((*it) != (*it2)) return false;
    it2++;
  }
  return true;
}
set<pair<int, int> > st;
inline bool checkup(int u, int v) {
  if (st.count(make_pair(u, v))) {
    return true;
  }
  st.insert(make_pair(u, v));
  for (int i = 0; i < N; i++) {
    if (start.boss(i) == u && finish.boss(i) != v) {
      return false;
    }
    if (start.boss(i) != u && finish.boss(i) == v) {
      return false;
    }
  }
  if (!set_eq(start.room[u].key, finish.room[v].key)) {
    return false;
  }
  if (!set_eq(start.room[u].people, finish.room[v].people)) {
    return false;
  }
  return true;
}
inline bool check() {
  for (int i = 0; i < N; i++) {
    int u = start.boss(i), v = finish.boss(i);
    if (!checkup(u, v)) {
      return false;
    }
  }
  return true;
}
int main() {
  scanf("%d %d %d", &N, &M, &K);
  for (int i = 0; i < M; i++) {
    scanf("%d %d", &edge[i].first, &edge[i].second);
    edge[i].first--;
    edge[i].second--;
  }
  start.init();
  finish.init();
  start.process();
  finish.process();
  if (check()) {
    printf("YES\n");
  } else {
    printf("NO\n");
  }
  return 0;
}
