#include <bits/stdc++.h>
using namespace std;
int ToInt(string& s, int len) {
  int r = 0;
  for (int i = 0, max_ = (len); i < max_; ++i) {
    r *= 10;
    r += s[i] - '0';
  }
  return r;
}
int GCD(int a, int b) { return b != 0 ? GCD(b, a % b) : a; }
int LCM(int a, int b) { return a * (b / GCD(a, b)); }
long long Pow(long long n, long long e) {
  if (e == 0) return 1;
  if (e == 1)
    return n;
  else if (e & 1) {
    long long t = Pow(n, e / 2);
    return n * t * t;
  } else {
    long long t = Pow(n, e / 2);
    return t * t;
  }
}
vector<int> compTasks[3];
int compID[201];
bool used[201];
int pred[201], tmp[201];
vector<int> edge[201];
void ProcessTask(int compId, int taskID, queue<int>& q) {
  for (int j = 0, max_ = ((int)(edge[taskID]).size()); j < max_; ++j) {
    int id = edge[taskID][j];
    --pred[id];
    if (pred[id] == 0 && compID[id] == compId && !used[id]) q.push(id);
  }
  used[taskID] = true;
}
int main() {
  int N, t, n;
  while (scanf("%d", &N) == 1) {
    memset(pred, 0, sizeof(pred));
    ;
    for (int i = 0, max_ = (3); i < max_; ++i) compTasks[i].clear();
    for (int i = 0, max_ = (201); i < max_; ++i) edge[i].clear();
    for (int i = 0, max_ = (N); i < max_; ++i) {
      scanf("%d", &t);
      compTasks[t - 1].push_back(i);
      compID[i] = t - 1;
    }
    for (int i = 0, max_ = (N); i < max_; ++i) {
      scanf("%d", &t);
      for (int j = 0, max_ = (t); j < max_; ++j) {
        scanf("%d", &n);
        ++pred[i];
        edge[n - 1].push_back(i);
      }
    }
    int minCost = numeric_limits<int>::max();
    memcpy(tmp, pred, sizeof(tmp));
    for (int start = 0, max_ = (3); start < max_; ++start) {
      memset(used, false, sizeof(used));
      ;
      memcpy(pred, tmp, sizeof(tmp));
      int todo = N, cost = 0;
      int compId = start;
      while (true) {
        queue<int> q;
        for (int i = 0, max_ = ((int)(compTasks[compId]).size()); i < max_;
             ++i) {
          int taskID = compTasks[compId][i];
          if (used[taskID]) continue;
          if (pred[taskID] == 0) {
            --todo;
            ProcessTask(compId, taskID, q);
          }
        }
        while (!q.empty()) {
          int taskID = q.front();
          q.pop();
          if (used[taskID]) continue;
          --todo;
          ProcessTask(compId, taskID, q);
        }
        compId = (compId + 1) % 3;
        if (todo == 0) break;
        ++cost;
      }
      minCost = std::min(minCost, cost + N);
    }
    printf("%d\n", minCost);
  }
  return 0;
}
