#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <complex> // complex<double> a(1.2 , 2.3);// real(): 1.2, imag()2.3
using namespace std;

#define MOD 1000000007
#define ll long long
#define ld long double
#define FOR(i,a,b) for(ll i=(ll)a;i<(ll)b;i++)
#define rep(i,n) FOR(i,0,n)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define rmsame(a) sort(all(a)),a.erase(unique(all(a)), a.end())
#define rmvector(a,b) rep(i,a.size())rep(j,b.size())if(a[i]==b[j]){a.erase(a.begin()+i);i--;break;}
#define first_more_idx(ve, num) upper_bound(all(ve), num)-ve.begin() // idx = first_more_idx(ve,num); if(idx = ve.size()) , then not exist
#define first_lessequal_idx(ve, num) lower_bound(all(ve), num)-ve.begin()
#define pq_pair_tB priority_queue <pair<ll,ll>, vector<pair<ll,ll> > , greater<pair<ll,ll> > >
#define pq_pair_ts priority_queue <pair<ll,ll> > // only sort first param
template<typename X> bool exist(vector<X> vec, X item){return find(all(vec), item)!=vec.end();}
ll gcd(ll a, ll b){if(b==0)return a;return gcd(b,a%b);}
ll lcm(ll a, ll b){return a/gcd(a,b)*b;}
ll power(ll x, ll n){if(n == 0) return 1;return  (n%2)? x*power(x, n-1)%MOD : power(x*x%MOD, n/2);}
ll dx[]={0, 0, -1, 1};
ll dy[]={1, -1, 0, 0};// up,down,left right

ll N ;
vector<ll> G[11234567];
vector<ll> root;
vector<ll> node_numebr;
vector<ll> till_end[11234567];

void inp_procedure(){
    bool not_root[1123457];
    
    ll before;
    ll now;
    cin >> N ;
    rep(i, N){
        rep(j, N-1){
            ll inp; cin >> inp;
            inp--;
            
            ll a = min(i, inp);
            ll b = max(i, inp);
            
            now = a * N + b;
            node_numebr.pb(now);
            
            if(j != 0){
                not_root[now] = true;
                G[before].pb(now);
            }
            before = now;
        }
    }
    rmsame(node_numebr);
    rep(i, node_numebr.size()){
        ll node = node_numebr[i];
        if(not_root[node]) continue;
        else root.pb(node);
    }
}

bool usedInLoop[1123456];
bool checkedInLoop[1123456];

bool check_loop(ll node){
    if(checkedInLoop[node])return false;
    
    if(usedInLoop[node]) return true;
    
    usedInLoop[node] = true;
    
    rep(i, G[node].size()){
        if(check_loop(G[node][i]))return true;
    }
    usedInLoop[node] = false;
    
    checkedInLoop[node] = true;
    
    return false;
}

ll dist_tillend[1123456];

ll cal_dist(ll node){
    if(dist_tillend[node] != 0) return dist_tillend[node];
    
    ll dist = 0;
    if(G[node].size() == 0) {
        dist_tillend[node] = 1;
        return 1;
    }
    
    rep(i, G[node].size()){
        dist = max(dist, cal_dist(G[node][i]));
    }
    return dist_tillend[node] = dist + 1;
    
}

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

    inp_procedure();
    
    if( root.size()== 0){
        cout << -1 << endl;
        cerr << "size = 0" << endl;
        return 0;
    }
        
    rep(i, root.size()){
        if(check_loop(root[i])){
            cerr << "loop" << endl;
            cout << -1 << endl;
            return 0;
        }
    }

    ll ans = 0;
    rep(i, root.size()){
        ans = max(ans, cal_dist(root[i]));
    }
    
    cout << ans << endl;

    //cout << fixed << setprecision(16) << ans << endl;
    return 0;
}


Measured memory_bytes: 562536