// clang++ -std=c++14 -W -O2 -DLOCAL
#include <iostream> // cin, cout, string
#include <algorithm> // sort, min/max, upper/lower_bound, transform, count/copy_if
#include <vector>
#include <utility> // pair, swap
#include <functional>
#include <iomanip> // setprecision
#include <map>
#include <set> // multiset
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <stack>
#include <queue> // priority_queue
#include <deque>
#include <bitset>
#include <array>
#include <list>
#include <forward_list>
#include <complex>
#include <ratio>
#include <cassert>
#include <numeric> // accumulate, itoa
#include <random> // mt19937
#include <chrono>
#include <iterator>
#include <boost/range/irange.hpp>
#include <boost/optional.hpp>
// #include <optional>
// #include <boost/type_index.hpp>
// #include <boost/multiprecision/cpp_int.hpp>

using namespace std;

// #define int long long
#define val const auto&
#define var auto&&

using i64 = int64_t;
using mnt = intmax_t;

using ll = long long;
using ld = long double;

template<typename T=int64_t> using vec = vector<T>;
template<typename T=int64_t> using mat = vec<vec<T>>;
template<typename T=int64_t> using dic = map<string, T>;
template<typename T=int64_t> using dic2 = unordered_map<string, T>;
template<typename T=int64_t, typename U=int64_t> using pr = pair<T, U>;
template<typename T=int64_t> using pqg = priority_queue<T, vector<T>, greater<T>>; // dijkstra
// template<typename... Args> using func = function<Args...>;
// template<typename T=int64_t> using pq = priority_queue<T>;

using pii = pr<int, int>;

using vi = vec<int>;
using mi = mat<int>; // graph
using vp = vec<pii>;
using vb = vec<bool>;

// using cint = boost::multiprecision::cpp_int;
using boost::irange;
template<typename T> using maybe = boost::optional<T>;

constexpr int IINF =  0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
// constexpr int INF = sizeof(int) == sizeof(long long) ? LINF : IINF;
constexpr long long MOD = 1e9+7;

#define _overload(_1,_2,_3,name,...) name
#define _rep1(i,a,b) for(int i=(a), _##i##_=(b);i<_##i##_;++i)
#define _rep2(i,n) _rep1(i,0,n)
#define _rep3(n) _rep2(i,n)
#define rep(...) _overload(__VA_ARGS__,_rep1,_rep2,_rep3)(__VA_ARGS__)
#define _rrep1(i,a,b) for(int i=(b)-1, _##i##_=(a);i>=_##i##_;--i)
#define _rrep2(i,n) _rrep1(i,0,n)
#define _rrep3(n) _rrep2(i,n)
#define rrep(...) _overload(__VA_ARGS__,_rrep1,_rrep2,_rrep3)(__VA_ARGS__)

#define each(i,a) for(auto&& i:a)
#define each2(i,a) for(const auto& i:a)

#define pb push_back
// emplace_back(...) == push_back(constructor(...))
#define eb emplace_back
#define pob pop_back
#define pf push_front
#define pof pop_front

#define np next_permutation
#define pp prev_permutation

// make_pair(A, B) == pair<T, U>(A, B)
// mt(...) == tie(...)
#define mp make_pair
#define mt make_tuple

#define ft first
#define sd second

#define all(a) std::begin(a), std::end(a)
#define rall(a) std::rbegin(a), std::rend(a)

// #define sum(a) accumulate(all(a), 0)
#define elif else if
#define unless(a) if(!(a))
#define qt(a) #a

#define endl '\n'
#define dec(n) fixed << setprecision(n)
#define zfl(n) setfill(‘0’) << setw(n)

template<typename T> inline constexpr int sz(const T &a) { return (int)(a).size(); };
template<typename T> inline constexpr T &rev(T &a) { reverse(std::begin(a), std::end(a)); return a; }
template<typename T, typename U> inline constexpr T &rs(T &a, const U &l) { a.resize(l); return a; }
template<typename T> inline constexpr T &sort(T &a) { sort(std::begin(a), std::end(a)); return a; }

inline constexpr char _upper(char c) { return ('a' <= c && c <= 'z' ? c-'a'+'A' : c); }
inline string &upper(string &s) { transform(s.begin(), s.end(), s.begin(), _upper); return s; }
inline constexpr char _lower(char c) { return ('A' <= c && c <= 'Z' ? c-'A'+'a' : c); }
inline string &lower(string &s) { transform(s.begin(), s.end(), s.begin(), _lower); return s; }

template<typename T=int, T l=0, T r=(T)MOD>
auto rnd = bind(uniform_int_distribution<T>(l, r), mt19937(chrono::steady_clock::now().time_since_epoch().count()));

template<typename T> inline constexpr T gcd2(T a, T b) { if(a==0 || b==0) return 0; while(b) { a = a%b; swap(a, b); } return a; }
template<typename T> inline constexpr T extgcd2(T a, T b, T &x, T &y) { x = 1; y = 0; while (b) { T t = a / b; a -= t * b; swap(a, b); x -= t * y; swap(x, y); } return a; }
template<typename T> inline constexpr T lcm(T a, T b) { return a / gcd(a, b) * b; }

template<typename T> inline constexpr bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<typename T> inline constexpr bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

template<typename A, typename B> istream &operator>>(istream &is, pair<A, B> &p) { is >> p.first; is >> p.second; return is; }
template<typename A, typename B> ostream &operator<<(ostream &os, const pair<A, B> &p) { os << p.first << " " << p.second; return os; }

template<typename T> istream &operator>>(istream &is, vector<T> &v) { for(auto&& x : v) is >> x; return is; }
template<typename T> ostream &operator<<(ostream &os, const vector<T> &v) { for(int i=0; i<(int)v.size(); ++i) os << v[i] << ( i+1 != (int)v.size() ? " " : "" ); return os; }

struct IOinit {
  IOinit() {
    cin.tie(nullptr); cout.tie(nullptr); ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    #ifdef LOCAL
      #define debug(x) cerr << "L" << __LINE__ << " | " << #x << ": " \
      /* << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() \ */\
      << " = " << (x) << endl
      #define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    #else
      #define debug(x)
      #define trace(...)
      cerr.rdbuf(nullptr);
    #endif
  }
} ioinit;
template <typename Arg> void __f(const char* name, const Arg& arg) { cerr << name << " : " << arg << endl; }
template <typename Arg, typename... Args> void __f(const char* names, const Arg& arg, const Args&... args)
{ const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg << " | "; __f(comma+1, args...); }

inline auto yes(const bool &c) { return c ? "yes" : "no"; }
inline auto Yes(const bool &c) { return c ? "Yes" : "No"; }
inline auto YES(const bool &c) { return c ? "YES" : "NO"; }
inline auto Possible(const bool &c) { return c ? "Possible" : "Impossible"; }
inline auto POSSIBLE(const bool &c) { return c ? "POSSIBLE" : "IMPOSSIBLE"; }

constexpr int lim = 1e5+7;

int N;
mi A;

vi B;
vb C;
queue<int> D, E;

signed main() {

  cin >> N;
  rs(A, N);
  rep(i, N) rs(A[i], N-1);
  cin >> A;
  rep(i, N) rep(j, N-1) --A[i][j];

  rs(B, N); rep(i, N) B[i] = 0;
  rs(C, N);

  int ans = 0;
  bool f = true;
  rep(i, N) D.push(i);
  while(f) {
    f = false;
    rep(i, N) C[i] = true; // 試合ができる
    while(!D.empty()) {
      int i = D.front(); D.pop();
      if(!C[i] || B[i]==N-1) continue; // 終
      int j = A[i][B[i]];
      if(C[j] && A[j][B[j]] == i) {
        ++B[i];
        ++B[j];
        C[i] = C[j] = false;
        E.push(i); E.push(j);
        f = true; // 試合をした
      }
    }
    D.swap(E);
    queue<int> F;
    E.swap(F);
    if(f) ++ans;
  }

  f = true;
  rep(i, N) {
    if(B[i]<N-1) {
      f = false;
      break;
    }
  }

  cout << (f ? ans : -1) << endl;

  return 0;
}


Measured memory_bytes: 6272