#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <utility>
#include <numeric>
#include <deque>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <cmath>
#include <limits>
#include <cassert>

#define for0(i, n)    for (int i = 0  ; i <  (n); ++i)
#define for1n(i, n)   for (int i = 1  ; i <= (n); ++i)
#define for1(i, n)    for (int i = 1  ; i <  (n); ++i)
#define forn(i, n)    for (int i = 0  ; i <= (n); ++i)
#define forx(i, n, x) for (int i = (x); i <  (n); ++i)

using namespace std;

typedef long long ll;
typedef priority_queue<ll> pq;
typedef priority_queue<ll,vector<ll> ,greater<ll>> pql;
typedef stack<ll> stk;
typedef queue<ll> qu;

struct arc{
    int to;
    int cost;
};

template<typename T>
struct node{
    T value;
    vector<arc> arcs;
    node(T v) : value(v){}

    node& operator= (T const& a){
        value = a;
        return *this;
    }
    operator T() const {
        return value;
    }

};

template<typename T>
class graph{
protected:
    vector<node<T>> nodes;

public:

    graph(int N, T value) : nodes(N, value){};

    void addArc(int from, int to, int cost){
        nodes[from].arcs.push_back({to, cost});
    }
    void addEdge(int a, int b, int cost){
        addArc(a, b, cost);
        addArc(b, a, cost);
    }
    node<T>& operator[](int index) {
        return nodes[index];
    }
    auto begin() { return nodes.begin(); }
    auto end()   { return nodes.end();   }

    operator vector<node<T>>() {
        return nodes;
    }
};

class bellmanford : public graph<int>{
    int N;
    int changed;

    void r(unordered_set<int> froms, int termination){
        bool c = false;
        unordered_set<int> f;
        for (auto& from : froms){
            for (auto& i : nodes[from].arcs) {
                if (nodes[i.to].value > i.cost + nodes[from].value) {
                    nodes[i.to].value = i.cost + nodes[from].value;
                    f.insert(i.to);
                    c = true;
                }
            }
        }
        // Terminated
        if (!c) return;

        // Negative loop?
        if(!termination){
            changed = c;
            return;
        }
        // continue
        r(move(f), termination-1);
    }

public:

    bellmanford(int N): graph::graph(N, std::numeric_limits<int>::max()),
                        N(N), changed(false){}

    bool run(int start){
        nodes[start].value = 0;
        r({start}, N-1);
        return changed;
    }

    int const& operator[] (int index){
        return nodes[index].value;
    }

};

inline int index(int a, int b, int N){
    if (a > b) swap(a, b);
    assert(a < b);
    return (a - 1) * (2 * (N - 1) - (a - 2) * 1) / 2 + (b - a) - 1;
}

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

    cin >> N;

    graph<int> g(N * (N - 1) / 2, 0);
    int arcn = 0;

    for1n(i, N){
        int bef;
        cin >> bef;
        for0(j, N - 2){
            int a;
            cin >> a;

            int befi = index(i, bef, N);
            int ai = index(i, a, N);

            g.addArc(befi, ai, 0);
            ++(g[ai].value);
            bef = a;
            ++arcn;
        }
    }

    int result = 0;
    vector<node<int>> v, w;
    vector<node<int>> &&tmp = vector<node<int>>(g);
    auto *vp = &tmp;

    while(true){

        for(auto x : *vp){
            if (x.value == -1) continue;
            if (x.value == 0){
                v.push_back(x);
                x.value = -1;
            }
        }

        if (v.empty()) break;

        w.clear();
        for(auto &t : v){
            for(auto &l : t.arcs){
                --g[l.to].value;
                w.push_back(g[l.to]);
                --arcn;
            }
        }

        ++result;
        v.clear();
        vp = &w;
    }

    // for0(i, N * (N - 1) / 2){
    //     if (g[i].value != -1){
    //         cout << -1;
    //         return 0;
    //     }
    // }

    if (arcn) {
        cout << -1;
        return 0;
    }

    cout << result;

    return 0;
}


Measured memory_bytes: 62720