#include <iostream>
#include <vector>
#include <array>
#include <set>
#include <cmath>
#include <string>
#include <queue> 
#include <list>
#include <stack>
#include <unordered_map>
#include <algorithm> 
#include <numeric>  
#include <functional>
#include <cassert>
#include <bitset>
#include <cctype>  
#include <iomanip> 
#include <limits>  
// std::numeric_limits<int>::max(), min()
// std::setprecision(X)
// std::islower(), std::isupper(), std::tolower, std::toupper
// std::accumulate(m.begin(), m.end(), 0LL);
// std::sort(begin(),end()) // 0, 1, 2, 3 ,4 (default, less);
// std::priority_queue<int, vector<int>, less<int>> que; // 4, 3, 2, 1 (defualt, less) : 
 
#define  rep(i, n) for(int i = 0; i < (int)(n);    i++)
#define rrep(i, n) for(int i = ((int)(n)-1); i>=0; i++)
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
typedef long long ll;

ll gcd ( ll a, ll b ) { if ( b == 0 ) return a; else return gcd ( b, a%b ); }
ll lcm ( ll a, ll b ) { return a * b / gcd(a, b); }

std::vector<std::vector<int>> from,to;
std::vector<int> dp;
int sol(int k) {
  if ( dp[k] != -1 ) return dp[k];
  if ( from[k].size() == 0 ) return dp[k] = 1;
  int rtn = 0;
  for(auto&& t : from[k]) rtn = std::max(rtn, sol(t)+1);
  return dp[k] = rtn;
}

int main (void) {
  std::cin.tie(0);  std::ios::sync_with_stdio(false);

  int N; std::cin >> N;
  std::vector<std::vector<int>> A(N, std::vector<int>(N-1));
  for(int i=0; i<N; i++) for(int j=0; j<N-1; j++) { std::cin >> A[i][j]; A[i][j]--; }


  // (1) worst solution : O(N*N*N)
  /*
  std::vector<int> index(N);
  int day;
  for(day=1; ; day++) {
    bool update = false;
    for(int i=0; i<N; i++) {
      if ( index[i] == N-1 ) continue;
      int Y = A[i][index[i]];
      if ( (i < Y && A[Y][index[Y]] == i) || (i > Y && A[Y][index[Y]-1] == i) ) {
        index[i]++;
        update = true;
      }
    }
    bool check = false;
    for(int i=0; i<N; i++) if ( index[i] != N-1 ) check = true;
    if ( !check ) break;

    if ( !update ) {
      std::cout << -1 << std::endl;
      return 0;
    }
  }
  std::cout << day << std::endl;
  */


  // (2) : faster than (1)
  /*
  std::vector<int> index(N);
  std::vector<std::pair<int,int>> q;
  auto check = [&](int I) {
    if ( index[I] == N-1 ) return;
    int Y = A[I][index[I]];
    if ( A[Y][index[Y]] == I ) { 
      if( I < Y ) std::swap(I,Y);
      q.push_back( std::pair<int,int>(I,Y) );
    }
    return;
  };
  rep(i,N) check(i);

  int day;
  for(day=1; ; day++) {
    std::sort( all(q) );
    q.erase( std::unique( all(q) ), q.end() );
    std::vector<std::pair<int,int>> PrevQ; std::swap(PrevQ, q);
    for(auto&& n : PrevQ) {
      index[n.first]++;
      index[n.second]++;
    }
    for(auto&& n : PrevQ) {
      check(n.first);
      check(n.second);
    }
    if(sz(q) == 0) break;
  }
  rep(i,N) if ( index[i] != N-1 ) { std::cout << -1 << std::endl; return 0; }
  std::cout << day << std::endl;
  */
  
  // Graph : DFS
  std::vector<std::vector<int>> name(N, std::vector<int>(N));
  int v = 0;
  for(int i=0; i<N; i++) for(int j=i+1; j<N; j++) { name[i][j] = v; v++; }
  auto vtxname = [&] (int i, int j) {
    if ( i > j ) std::swap(i,j);
    return name[i][j];
  };
  from.resize(N*N);
  to.resize(N*N);
  std::vector<int> dim(N*N);
  for(int i=0; i<N; i++) {
    for(int j=0; j<N-1; j++) {
      int nowv = vtxname(i, A[i][j]);
      if ( j < N-2 ) {
        int nextv = vtxname(i, A[i][j+1]);
        to[nowv].push_back(nextv);
      }
      if ( j > 0 ) {
        int prev = vtxname(i, A[i][j-1]);
        from[nowv].push_back(prev);
        dim[nowv]++;
      }
    }
  }

  std::vector<int> tsort;
  std::stack<int> st;
  for(int i=0; i<v; i++) if ( dim[i] == 0 ) { st.push(i); tsort.push_back(i); }
  while(!st.empty()) {
    int cur = st.top(); st.pop();
    for(auto&& k : to[cur]) {
      dim[k]--;
      if ( dim[k] == 0 ) {
        st.push(k);
        tsort.push_back(k);
    }
    }
  }

  if ( sz(tsort) != N*(N-1)/2 ) {
    std::cout << -1 << std::endl;
    return 0;
  }

  // dp
  dp.assign(v, -1);
  int ans = -1;
  for(int i=0; i<v; i++) ans = std::max(ans, sol(i));
  std::cout << ans << std::endl;

  return 0;
}


Measured memory_bytes: 94196