Problem:
Score : 500 points

Problem Statement

N players will participate in a tennis tournament. We will call them Player 1, Player 2, \ldots, Player N.

The tournament is round-robin format, and there will be N(N-1)/2 matches in total.
Is it possible to schedule these matches so that all of the following conditions are satisfied? If the answer is yes, also find the minimum number of days required.

Each player plays at most one matches in a day.

Each player i (1 \leq i \leq N) plays one match against Player A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} in this order.

Constraints

3 \leq N \leq 1000

1 \leq A_{i, j} \leq N

A_{i, j} \neq i

A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} are all different.

Input

Input is given from Standard Input in the following format:

N
A_{1, 1} A_{1, 2} \ldots A_{1, N-1}
A_{2, 1} A_{2, 2} \ldots A_{2, N-1}
:
A_{N, 1} A_{N, 2} \ldots A_{N, N-1}

Output

If it is possible to schedule all the matches so that all of the conditions are satisfied, print the minimum number of days required; if it is impossible, print -1.

Sample Input 1

3
2 3
1 3
1 2

Sample Output 1

3

All the conditions can be satisfied if the matches are scheduled for three days as follows:

Day 1: Player 1 vs Player 2

Day 2: Player 1 vs Player 3

Day 3: Player 2 vs Player 3

This is the minimum number of days required.

Sample Input 2

4
2 3 4
1 3 4
4 1 2
3 1 2

Sample Output 2

4

All the conditions can be satisfied if the matches are scheduled for four days as follows:

Day 1: Player 1 vs Player 2, Player 3 vs Player 4

Day 2: Player 1 vs Player 3

Day 3: Player 1 vs Player 4, Player 2 vs Player 3

Day 4: Player 2 vs Player 4

This is the minimum number of days required.

Sample Input 3

3
2 3
3 1
1 2

Sample Output 3

-1

Any scheduling of the matches violates some condition.

Solution in C++14 (Clang 3.8.0) (judge verdict: Time Limit Exceeded)

// 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;

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;
  while(f) {
    f = false;
    rep(i, N) C[i] = true; // 試合ができる
    rep(i, N) {
      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;
        f = true; // 試合をした
      }
    }
    cerr << B << endl;
    if(f) ++ans;
  }

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

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

  return 0;
}