#include <bits/stdc++.h>
#include <boost/format.hpp>
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#define rep(i, n) repr((i), 0, (n))
#define repr(i, a, t) reps((i), (a), (t), 1)
#define reps(i, a, t, s) for (long long (i) = (a); (i) < (long long)(t); (i) += (s))
#define rrep(i, n) rrepr((i), (n) - 1, 0)
#define rrepr(i, a, t) rreps((i), (a), (t), 1)
#define rreps(i, a, t, s) for (long long (i) = (a); (i) >= (long long)(t); (i) -= (s))
#define each(v, c) for (auto &&(v) : (c))
#define all(c) (c).begin(), (c).end()
using namespace std;
namespace mp = boost::multiprecision;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using ml = mp::cpp_int;
const long long MOD = 1e9 + 7;
const long long INF = 1e18;

template<typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  if (v.empty()) return os << "vector{}";
  os << "vector{" << *v.begin();
  for (auto it = ++v.begin(); it != v.end(); ++it)
    os << ", " << *it;
  return os << "}";
}
template<typename T>
ostream &operator<<(ostream &os, const set<T> &s) {
  if (s.empty()) return os << "set{}";
  os << "set{" << *s.begin();
  for (auto it = ++s.begin(); it != s.end(); ++it)
    os << ", " << *it;
  return os << "}";
}
template<typename S, typename T>
ostream &operator<<(ostream &os, const map<S, T> &m) {
  if (m.empty()) return os << "map{}";
  os << "map{" << (*m.begin()).first << ": " << (*m.begin()).second;
  for (auto it = ++m.begin(); it != m.end(); ++it)
    os << ", " << (*it).first << ": " << (*it).second;
  return os << "}";
}
template<typename S, typename T>
ostream &operator<<(ostream &os, const pair<S, T> &p) {
  return os << "pair{" << p.first << ", " << p.second << "}";
}

ll dfs(ll v, unordered_map<ll, vector<ll>> &graph, unordered_map<ll, ll> &memo) {
  if (memo[v] > 0) {
    return memo[v];
  }
  ll ret = 0;
  each (u, graph[v]) {
    ret = max(ret, dfs(u, graph, memo));
  }
  return memo[v] = ret + 1;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  ifstream ifs;
  if (getenv("LOCAL") != nullptr) {
    ifs.open("src/_in.txt");
    cin.rdbuf(ifs.rdbuf());
  }


  ll N;
  cin >> N;
  vector<vector<ll>> A(N, vector<ll>(N - 1));
  rep (i, N) {
    rep (j, N - 1) {
      cin >> A[i][j];
    }
  }

  unordered_set<ll> nodes, sources;
  unordered_map<ll, vector<ll>> graph;
  unordered_map<ll, ll> ins;

  rep (i, N) {
    rep (j, N - 2) {
      ll a, b, c, d;
      a = i;
      b = A[i][j] - 1;
      c = i;
      d = A[i][j + 1] - 1;
      if (a > b) {
        swap(a, b);
      }
      if (c > d) {
        swap(c, d);
      }
      graph[a * N + b].push_back(c * N + d);
      ins[c * N + d] += 1;
      sources.insert(a * N + b);

      nodes.insert(a * N + b);
      nodes.insert(c * N + d);
    }
  }

  vector<ll> S;
  each (v, sources) {
    if (ins[v] == 0) {
      S.push_back(v);
    }
  }
  vector<ll> L;
  while (S.size()) {
    ll v = S.back();
    S.pop_back();
    L.push_back(v);
    each (u, graph[v]) {
      ins[u] -= 1;
      if (ins[u] == 0) {
        S.push_back(u);
      }
    }
  }
  if (L.size() != nodes.size()) {
    cout << -1 << "\n";
    return 0;
  }

  unordered_map<ll, ll> memo;
  each (v, nodes) {
    memo[v] = -1;
  }

  ll ans = 0;
  each (v, sources) {
    ans = max(ans, dfs(v, graph, memo));
  }
  cout << ans << "\n";
}


Measured memory_bytes: 133952