#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define REP(i,n) for (int i = 1; i < (int)(n); i++)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define debug(var) do{cout << #var << " : "; view(var);}while(0)
template<class T> bool chmin(T &a, T b) {if(a>b) {a=b;return 1;}return 0;}
template<class T> bool chmax(T &a, T b) {if(a<b) {a=b;return 1;}return 0;}
using namespace std;
template<class T> void view(T e) {cout << e << endl;}
template<class T> void view(const vector<T> &v) {for(const auto &e : v){cout << e << " ";} cout << endl;}
template<class T> void view(const vector<vector<T>> &vv) {for(const auto &v : vv){view(v);}}
using vint = vector<int>;
using vvint = vector<vector<int>>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<int,int>;
const int inf = 1e9;
const ll inf_l = 1e18;
const int MAX = 1e5;

struct topological_sort{
    vector<vector<int>> G;
    vector<int> indegree;
    vector<int> degree;
    int V;

    topological_sort(int V) : V(V) {
        G.resize(V); 
        indegree.resize(V);
        degree.resize(V);
    }
    void add_edge(int a, int b) {
        G[a].push_back(b);
        indegree[b]++;
    }
    vector<int> sort() {
        queue<int> q;
        vector<int> sorted;
        int deg = 1;
        for (int i = 0; i < V; i++) {
            if (indegree[i] == 0) {
                q.push(i);
                degree[i] = deg;
            }
        }
        while (!q.empty()) {
            queue<int> q_tmp;
            deg++;
            while (!q.empty()) {
                int v = q.front(); q.pop();
                for (int i = 0; i < G[v].size(); i++) {
                    int u = G[v][i];
                    indegree[u]--;
                    if (indegree[u] == 0) {
                        q_tmp.push(u);
                        degree[u] = deg;
                    }
                }
                sorted.push_back(v);
            }
            swap(q,q_tmp);
        }
        return sorted;
    }
};

int main() {
    int n; cin >> n;
    topological_sort ts(n*(n-1)/2);
    vvint to(n,vint(n));
    int num = 0;
    rep(i,n)rep(j,i) to[j][i] = to[i][j] = num++;
    vvint data(n,vint(n-1));
    rep(i,n)rep(j,n-1) {
        int x; cin >> x;
        x--;
        data[i][j] = x;
    }
    rep(i,n)rep(j,n-2) {
        ts.add_edge(to[i][data[i][j]],to[i][data[i][j+1]]);
    }
    vint res = ts.sort();
    if (res.size() != n*(n-1)/2) {cout << -1 << endl; return 0;}
    cout << ts.degree[res.back()] << endl;
}
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <complex>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <regex>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define rep(i, n) for (ll i = 0; i < (n); ++i)
#define repLRE(i, l, r) for (ll i = (l); i <= (r); ++i)
#define rrepLRE(i, l, r) for (ll i = (l); i >= (r); --i)
#define Sort(v) sort(v.begin(), v.end())
#define rSort(v) sort(v.rbegin(), v.rend())
#define Reverse(v) reverse(v.begin(), v.end())
#define Lower_bound(v, x) \
  distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) \
  distance(v.begin(), upper_bound(v.begin(), v.end(), x))

using ll = long long;
using ull = unsigned long long;
using P = pair<ll, ll>;
using T = tuple<ll, ll, ll>;
using vll = vector<ll>;
using vP = vector<P>;
using vT = vector<T>;
using vvll = vector<vector<ll>>;
using vvP = vector<vector<P>>;
using dqll = deque<ll>;

ll dx[9] = {-1, 1, 0, 0, -1, -1, 1, 1, 0};
ll dy[9] = {0, 0, -1, 1, -1, 1, -1, 1, 0};

/* Macros reg. ends here */

const ll INF = 1LL << 50;

int main() {
  // ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cout << fixed << setprecision(15);

  ll n;
  cin >> n;
  vector<queue<ll>> que(n);

  rep(i, n) {
    rep(_, n - 1) {
      ll a;
      cin >> a;
      a--;
      que[i].push(a);
    }
  }

  bool upd = true;
  ll tsukaday = 0;
  while (upd) {
    upd = false;
    vll done(n);
    rep(i, n) {
      if (done[i] || que[i].empty()) continue;
      ll toi = que[i].front();
      if (done[toi] == 0 && que[toi].front() == i) {
        que[i].pop();
        que[toi].pop();
        done[i] = 1;
        done[toi] = 1;
        upd = true;
      }
    }
    if(upd) tsukaday++;
  }

  bool ok = true;
  rep(i, n) if (!que[i].empty()) {
    ok = false;
    break;
  }

  ll ans = ok ? tsukaday : -1;
  cout << ans << endl;

  return 0;
}
