#include <bits/stdc++.h>
using namespace std;
std::mt19937 rnd(
    (int)std::chrono::steady_clock::now().time_since_epoch().count());
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXMUTRHSSUM = 100;
const int MAXMUT = MAXMUTRHSSUM;
const int MAXGENE = MAXMUT + 2;
const int MAXPATRHSSUM = 50;
const int MAXPAT = MAXPATRHSSUM;
const int MAXTOK = 2 + MAXMUTRHSSUM;
const int MAXTRIE = 1 + MAXPATRHSSUM;
const int MAXSINGLE = MAXMUTRHSSUM;
const int MAXPAIR = MAXMUTRHSSUM - 1;
const int ALPH = 2;
int ngene, nmut, npat;
vector<int> mut[MAXMUT];
int mutlhs[MAXMUT];
vector<int> muts[MAXGENE];
vector<int> pat[MAXPAT];
long long ans[MAXGENE];
int ntok, nsingle, npair, ntrie;
int singlelhs[MAXSINGLE], singlerhs[MAXSINGLE];
int pairlhs[MAXPAIR];
pair<int, int> pairrhs[MAXPAIR];
vector<int> singleusage[MAXTOK];
vector<pair<int, int>> pairusage[MAXTOK];
long long dp[MAXTOK][MAXTRIE][MAXTRIE];
priority_queue<pair<long long, pair<int, pair<int, int>>>> pq;
struct TrieNode {
  int nxt[ALPH];
  int safenxt[ALPH];
  int suff;
  bool detected;
};
TrieNode trie[MAXTRIE];
int trieroot;
int maketrie() {
  assert(ntrie < MAXTRIE);
  int ret = ntrie++;
  for (int i = (0); i < (ALPH); ++i)
    trie[ret].nxt[i] = trie[ret].safenxt[i] = -1;
  trie[ret].detected = false;
  trie[ret].suff = -1;
  return ret;
}
void buildtrie() {
  ntrie = 0;
  trieroot = maketrie();
  for (int i = (0); i < (npat); ++i) {
    int at = trieroot;
    for (int j = (0); j < (((int)(pat[i]).size())); ++j) {
      int x = pat[i][j];
      assert(0 <= x && x < ALPH);
      int to = trie[at].nxt[x];
      if (to == -1) {
        to = maketrie();
        trie[at].nxt[x] = to;
      }
      at = to;
    }
    trie[at].detected = true;
  }
  queue<int> q;
  q.push(trieroot);
  while (!q.empty()) {
    int at = q.front();
    q.pop();
    for (int k = (0); k < (ALPH); ++k) {
      int suff;
      if (at == trieroot) {
        suff = at;
      } else {
        suff = trie[at].suff;
        while (suff != trieroot && trie[suff].nxt[k] == -1)
          suff = trie[suff].suff;
        if (trie[suff].nxt[k] != -1) suff = trie[suff].nxt[k];
      }
      int to = trie[at].nxt[k];
      trie[at].safenxt[k] = to == -1 ? suff : to;
      if (to != -1) {
        trie[to].suff = suff;
        if (trie[suff].detected) trie[to].detected = true;
        q.push(to);
      }
    }
  }
}
void upd(int x, int s, int t, long long cost) {
  if (cost >= dp[x][s][t]) return;
  dp[x][s][t] = cost;
  pq.push(make_pair(-cost, make_pair(x, make_pair(s, t))));
}
void solve() {
  ntok = ngene, nsingle = 0, npair = 0;
  for (int i = (0); i < (nmut); ++i) {
    if (((int)(mut[i]).size()) == 1) {
      int idx = nsingle++;
      singlelhs[idx] = mutlhs[i];
      singlerhs[idx] = mut[i][0];
      continue;
    }
    int at = 0, last = mutlhs[i];
    while (at + 2 < ((int)(mut[i]).size())) {
      int next = ntok++, idx = npair++;
      pairlhs[idx] = last, pairrhs[idx] = make_pair(mut[i][at], next);
      ++at, last = next;
    }
    {
      int idx = npair++;
      pairlhs[idx] = last;
      pairrhs[idx] = make_pair(mut[i][at], mut[i][at + 1]);
    }
  }
  for (int i = (0); i < (nsingle); ++i) singleusage[singlerhs[i]].push_back(i);
  for (int i = (0); i < (npair); ++i)
    pairusage[pairrhs[i].first].push_back(make_pair(i, 0)),
        pairusage[pairrhs[i].second].push_back(make_pair(i, 1));
  buildtrie();
  for (int x = (0); x < (ntok); ++x)
    for (int s = (0); s < (ntrie); ++s)
      for (int t = (0); t < (ntrie); ++t) dp[x][s][t] = LLONG_MAX;
  for (int x = (0); x < (2); ++x)
    for (int s = (0); s < (ntrie); ++s)
      if (!trie[s].detected) {
        int t = trie[s].safenxt[x];
        if (!trie[t].detected) upd(x, s, t, 1);
      }
  while (!pq.empty()) {
    long long cost = -pq.top().first;
    int x = pq.top().second.first, s = pq.top().second.second.first,
        t = pq.top().second.second.second;
    pq.pop();
    if (cost > dp[x][s][t]) continue;
    for (int i = (0); i < (((int)(singleusage[x]).size())); ++i) {
      int idx = singleusage[x][i];
      int a = singlelhs[idx], b = singlerhs[idx];
      assert(b == x);
      upd(a, s, t, cost);
    }
    for (int i = (0); i < (((int)(pairusage[x]).size())); ++i) {
      int idx = pairusage[x][i].first, side = pairusage[x][i].second;
      int a = pairlhs[idx], b = pairrhs[idx].first, c = pairrhs[idx].second;
      if (side == 0) {
        assert(b == x);
        for (int tt = (0); tt < (ntrie); ++tt)
          if (dp[c][t][tt] != LLONG_MAX) upd(a, s, tt, cost + dp[c][t][tt]);
      }
      if (side == 1) {
        assert(c == x);
        for (int ss = (0); ss < (ntrie); ++ss)
          if (dp[b][ss][s] != LLONG_MAX) upd(a, ss, t, cost + dp[b][ss][s]);
      }
    }
  }
  for (int x = (2); x < (ngene); ++x) ans[x] = LLONG_MAX;
  for (int x = (2); x < (ngene); ++x)
    for (int t = (0); t < (ntrie); ++t)
      if (!trie[t].detected) ans[x] = min(ans[x], dp[x][trieroot][t]);
}
void run() {
  scanf("%d%d%d", &ngene, &nmut, &npat);
  for (int i = (0); i < (nmut); ++i) {
    int a, cnt;
    scanf("%d%d", &a, &cnt);
    vector<int> cur(cnt);
    for (int j = (0); j < (cnt); ++j) scanf("%d", &cur[j]);
    mutlhs[i] = a, mut[i] = cur;
    muts[a].push_back(i);
  }
  for (int i = (0); i < (npat); ++i) {
    int cnt;
    scanf("%d", &cnt);
    vector<int> cur(cnt);
    for (int j = (0); j < (cnt); ++j) scanf("%d", &cur[j]);
    pat[i] = cur;
  }
  solve();
  for (int i = (2); i < (ngene); ++i)
    if (ans[i] == LLONG_MAX)
      printf("YES\n");
    else
      printf("NO %lld\n", ans[i]);
}
int main() {
  run();
  return 0;
}
