#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <climits>
#include <random>
#include <iomanip>

using namespace std;
typedef long long unsigned int ll;
typedef pair<int, int> P;

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))

#define fillInt(xs, x)        \
  for (int i = 0; i < (x); i++) \
    scanf("%d", &xs[i]);
#define fillLong(xs, x)       \
  for (int i = 0; i < (x); i++) \
    scanf("%ld", &xs[i]);
#define fillString(xs, x)       \
  for (int i = 0; i < (x); i++) \
    cin >> xs[i];
#define sortv(xs) sort(xs.begin(), xs.end())
#define sortvdi(xs) sort(xs.begin(), xs.end(), std::greater<long>())
#define lbv(xs, x) lower_bound(xs.begin(), xs.end(), x) - xs.begin()
#define ubv(xs, x) upper_bound(xs.begin(), xs.end(), x) - xs.begin()
#define bs(xs, x) binary_search(xs.begin(), xs.end(), x)

#define rep(i,n) for(auto i=0; i<(n); i++)
#define isValidPoint(x, y, mx, my) x >= 0 && x  < mx && y >= 0 && y < my

int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};

const int mod = 1000000007;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res+=a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res-=a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res*=a;
  }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
 
  // for prime mod
  mint inv() const {
    return pow(mod-2);
  }
  mint& operator/=(const mint a) {
    return (*this) *= a.inv();
  }
  mint operator/(const mint a) const {
    mint res(*this);
    return res/=a;
  }
};

struct Pony
{
    long a, b;
 
    Pony(long a_, long b_)
    {
        a = a_;
        b = b_;
    }
 
    bool operator<(const Pony &another) const
    {
        return b < another.b;
    };
};

int fac(int k){
    int sum = 0;
    for (int i = 1; i <= k; ++i)
    {
        sum += i;
    }
    return sum;
}

int a[1005][1005];
int b[1005]; // 次のあいてるひ
int c[1005]; // 次の相手番号
bool d[1005];
int n;

int adj(int i, int j, int dt) {
  if (d[i]) {
    return -1;
  }
  d[i] = true;
  int aite = a[i][c[i]];
  int adjDt;
  if (aite == j) {
    adjDt = max(b[i], dt);
    c[i]++;
  } else {
    adjDt = b[i];
    while (aite != j) {
      adjDt = adj(aite, i, adjDt);
      if (adjDt == -1) return -1;
      adjDt++;
      c[i]++;
      aite = a[i][c[i]];
    }
    adjDt = max(adjDt, dt);
    c[i]++;
  }
  d[i] = false;
  b[i] = adjDt+1;
  return adjDt;
}

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

  cin >> n;

  rep(i, n) {
    c[i] = 0;
    rep(j, n-1) {
      int x;
      cin >> x;
      a[i][j] = x-1;
      b[i] = 1;
    }
  }

  bool fk = false;
  rep(i, n) {
    while(c[i] < n-1) {
      d[i] = true;
      int nxt = adj(a[i][c[i]], i, b[i]);
      d[i] = false;
      if (nxt == -1) {
        fk = true;
        break;
      }
      c[i]++;
      b[i] = nxt+1;
    }
    if (fk) break;
  }

  if (fk) {
       cout << -1 << endl;
  } else {
    int dt = 0;
    rep(i, n) {
      dt = max(dt, b[i]-1);
    }

    cout << dt << endl;
  }

}


Measured memory_bytes: 4224