// Slower C++ solution:
/**

 * Created by hiramekun at 11:15 on 2019-09-02.

 */

#include <bits/stdc++.h>



using namespace std;



using ll = long long;

using vl = vector<ll>;

using vvl = vector<vl>;

using P = pair<ll, ll>;

template<typename T> using pq = priority_queue<T>;

template<typename T> using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T, typename K> using ump = unordered_map<T, K>;

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

const ll mod = 1000000007;

const ll inf = ll(1e9);

const ll e5 = ll(1e5);

const ll ll_inf = ll(1e9) * ll(1e9);



#define rep(i, n) for(ll i = 0; i < (ll)(n); i++)

#define repr(i, n) for(ll i = ll(n - 1); i >= 0; i--)

#define each(i, mp) for(auto& i:mp)

#define eb emplace_back

#define F first

#define S second

#define all(obj) (obj).begin(), (obj).end()



template<class T>

ostream &operator<<(ostream &out, const vector<T> &list) {

    ll n = list.size();

    rep(i, n) out << list[i] << ' ';

    return out;

}





template<class T>

istream &operator>>(istream &in, vector<T> &list) {

    ll n = list.size();

    rep(i, n) in >> list[i];

    return in;

}



template<class T>

ostream &operator<<(ostream &out, const vector<vector<T>> &list) {

    ll n = list.size();

    rep(i, n) out << list[i] << '\n';

    return out;

}



/* ------------- ANSWER ------------- */

/* ---------------------------------- */



void solve() {

    ll n;

    scanf("%lli", &n);



    ll v[1000][1000];



    rep(i, n) {

        rep(j, n - 1) {

            ll a;

            scanf("%lli", &a);

            a--;

            v[i][j] = a;

        }

    }

    ll rem = n * (n - 1);

    ll ans = 0;

    ll idxs[1000] = {0};



    while (rem > 0) {

        bool done[1000] = {false};



        bool plus = false;

        rep(i, n) {

            if (done[i]) continue;

            if (idxs[i] >= n - 1) continue;

            ll j = v[i][idxs[i]];

            if (done[j]) continue;

            if (j >= n - 1) continue;

            if (idxs[j] >= n - 1) continue;



            if (v[j][idxs[j]] == i) {

                done[i] = done[j] = true;

                idxs[i]++, idxs[j]++;

                rem -= 2;



                if (!plus) {

                    plus = true;

                    ans++;

                }

            }

        }

        if (!plus) {

            printf("%i", -1);

            return;

        }

    }

    printf("%lli", ans);

}



int main() {

#ifdef MY_DEBUG

    while (true) {

#endif

        solve();

#ifdef MY_DEBUG

    }

#endif

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.1641599287594753x):
/**

 * Created by hiramekun at 15:11 on 2019-09-02.

 */

#include <bits/stdc++.h>



using namespace std;



using ll = long long;

using vl = vector<ll>;

using vvl = vector<vl>;

using P = pair<ll, ll>;

template<typename T> using pq = priority_queue<T>;

template<typename T> using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T, typename K> using ump = unordered_map<T, K>;

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

const ll mod = 1000000007;

const ll inf = ll(1e9);

const ll e5 = ll(1e5);

const ll ll_inf = ll(1e9) * ll(1e9);



#define rep(i, n) for(ll i = 0; i < (ll)(n); i++)

#define repr(i, n) for(ll i = ll(n - 1); i >= 0; i--)

#define each(i, mp) for(auto& i:mp)

#define eb emplace_back

#define F first

#define S second

#define all(obj) (obj).begin(), (obj).end()



template<class T>

ostream &operator<<(ostream &out, const vector<T> &list) {

    ll n = list.size();

    rep(i, n) out << list[i] << ' ';

    return out;

}





template<class T>

istream &operator>>(istream &in, vector<T> &list) {

    ll n = list.size();

    rep(i, n) in >> list[i];

    return in;

}



template<class T>

ostream &operator<<(ostream &out, const vector<vector<T>> &list) {

    ll n = list.size();

    rep(i, n) out << list[i] << '\n';

    return out;

}



/* ------------- ANSWER ------------- */

/* ---------------------------------- */



void solve() {

    ll n;

    cin >> n;



    vector<queue<ll>> v(n);

    rep(i, n) {

        rep(j, n - 1) {

            ll a;

            cin >> a;

            v[i].push(--a);

        }

    }



    queue<ll> next;

    ll res = n * (n - 1);

    ll ans = 0;

    bool plus = false;

    vector<bool> seen(n);



    rep(i, n) {

        if (v[i].empty()) continue;

        ll j = v[i].front();

        if (v[j].empty()) continue;

        if (!seen[j] && !seen[i] && v[j].front() == i) {

            seen[i] = seen[j] = true;

            v[i].pop(), v[j].pop();

            next.push(i), next.push(j);

            res -= 2;

            plus = true;

        }

    }

    if (plus) ans++;

    else {

        cout << -1 << '\n';

        return;

    }



    while (res > 0) {

        bool plus = false;

        vector<bool> seen(n);

        queue<ll> tmp;

        while (!next.empty()) {

            ll now = next.front();

            next.pop();



            if (v[now].empty()) continue;

            ll j = v[now].front();

            if (v[j].empty()) continue;



            if (!seen[j] && !seen[now] && v[j].front() == now) {

                seen[j] = seen[now] = true;

                v[j].pop(), v[now].pop();

                tmp.push(j), tmp.push(now);

                res -= 2;

                plus = true;

            }

        }

        if (!plus) {

            cout << -1 << '\n';

            return;

        }

        ans++;

        next = tmp;

    }



    cout << ans << '\n';

}



int main() {

#ifdef MY_DEBUG

    while (true) {

#endif

        solve();

#ifdef MY_DEBUG

    }

#endif

    return 0;

}