using static System.Math;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System;

class Program
{
    #region Reader
    static string ReadStr => Console.ReadLine();
    static string[] ReadStrs => Console.ReadLine().Split(' ');
    static int ReadInt => Convert.ToInt32(Console.ReadLine().Trim());
    static int[] ReadInts => Console.ReadLine().Trim().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
    static long ReadLong => Convert.ToInt64(Console.ReadLine().Trim());
    static long[] ReadLongs => Console.ReadLine().Trim().Split(' ').Select(s => Convert.ToInt64(s)).ToArray();
    #endregion
    #region Method
    const int mod = 1000000007;
    public static int Mod(int a, int mod) { return a % mod >= 0 ? a % mod : a % mod + mod; }
    public static long Mod(long a, long mod = mod) { return a % mod >= 0 ? a % mod : a % mod + mod; }
    #endregion





    /// <summary>
    /// 最大公約数
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static long Gcd(long a, long b)
    {
        if (a < b)
            // 引数を入替えて自分を呼び出す
            return Gcd(b, a);
        while (b != 0)
        {
            var remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }



    public static Dictionary<int, int> PrimeFactors(int n)
    {
        int i = 2;
        int tmp = n;
        Dictionary<int, int> d = new Dictionary<int, int>();

        while (i * i <= n) //※1
        {
            if (tmp % i == 0)
            {
                tmp /= i;
                if (d.ContainsKey(i)) d[i]++;
                else d.Add(i, 1);
            }
            else
            {
                i++;
            }
        }
        if (tmp != 1)
        {
            if (d.ContainsKey(tmp)) d[tmp]++;
            else d.Add(tmp, 1);
        }
        return d;
    }


    #region Mod
    public static long GetInv(long a, long mod = 1000000007)
    {
        return PowerMod(a, mod - 2, mod);
    }
    public static long Combination(long a, long b, long mod = 1000000007)
    {
        if (b < 0 || b > a) return 0;
        if (b > a / 2) b = a - b;
        long numerator = Factorial(a, mod);
        long denominator = (Factorial(b, mod) * Factorial(a - b, mod)) % mod;

        return (numerator * GetInv(denominator, mod)) % mod;
    }
    public static long Factorial(long n, long mod = 1000000007)
    {
        if (n == 0) return 1;
        if (n == 1) return 1;
        long ans = n;
        for (int i = 2; i < n; i++)
        {
            ans = (ans * i) % mod;
        }

        return ans;
    }
    private static long PowerMod(long a, long n, long mod = 1000000007)
    {
        if (n == 0) return 1;
        if (n == 1) return a;

        long p = PowerMod(a, n / 2, mod);
        if (n % 2 == 1) return ((p * p) % mod * a) % mod;
        else return (p * p) % mod;
    }
    #endregion


    static List<long> Divisor(long N)
    {
        List<long> ans = new List<long>();
        int max = (int)Math.Sqrt(N);
        for (int i = 1; i < max; i++)
        {
            if (N % i == 0)
            {
                ans.Add(i);
                ans.Add(N / i);
            }
        }

        if (N % max == 0)
        {
            if (N / max == max) ans.Add(max);
            else
            {
                ans.Add(max);
                ans.Add(N / max);
            }
        }
        return ans;
    }


    class Segtree<T>
    {
        int n;
        T[] tree;
        Func<T, T, T> f;
        T exnum;
        public Segtree(int m, Func<T, T, T> f, T ex)
        {
            this.f = f;
            this.exnum = ex;
            n = 1;
            while (n < m) n <<= 1;

            tree = new T[(n << 1) - 1];
            for (int i = 0; i < tree.Length; i++) tree[i] = ex;
        }
        public Segtree(int m, T ini, Func<T, T, T> f, T ex) : this(m, f, ex)
        {
            for (int i = 0; i < m; ++i) tree[i + n - 1] = ini;
            all_update();
        }
        public void assign_without_update(int j, T x)
        {
            tree[j + n - 1] = x;
        }
        public void update(int j, T x)
        {
            int i = j + n - 1;
            tree[i] = x;
            while (i > 0)
            {
                i = (i - 1) >> 1;
                tree[i] = f(tree[(i << 1) + 1], tree[(i << 1) + 2]);
            }
        }
        public void all_update()
        {
            for (int i = n - 2; i >= 0; i--)
                tree[i] = f(tree[(i << 1) + 1], tree[(i << 1) + 2]);
        }
        public T look(int i) { return tree[i + n - 1]; }

        // [s, t)
        public T run(int s, int t) { return query(s, t, 0, 0, n); }
        T query(int s, int t, int k, int l, int r)
        {
            if (r <= s || t <= l) return exnum;
            if (s <= l && r <= t) return tree[k];

            return f(query(s, t, (k << 1) + 1, l, (l + r) >> 1), query(s, t, (k + 1) << 1, (l + r) >> 1, r));
        }
    }

    struct ModInt
    {
        const int MOD = 998244353;// 1000000007;
        long value;
        static List<ModInt> fact = new List<ModInt> { 1 };
        public ModInt(long value) => this.value = value;
        public static implicit operator ModInt(long a) => new ModInt(a % MOD + (a < 0 ? MOD : 0));
        public static explicit operator int(ModInt a) => (int)a.value;
        public static ModInt operator +(ModInt a, ModInt b) => a.value + b.value;
        public static ModInt operator -(ModInt a, ModInt b) => a.value - b.value;
        public static ModInt operator *(ModInt a, ModInt b) => a.value * b.value;
        public static ModInt operator /(ModInt a, ModInt b) => a * Inv(b);
        public static ModInt Pow(ModInt a, int n) { if (n == 0) return 1; if (n == 1) return a; var p = Pow(a, n / 2); return p * p * Pow(a, n % 2); }
        public static ModInt Inv(ModInt a) => Pow(a, MOD - 2);
        public static ModInt Fact(int n) { for (int i = fact.Count; i <= n; i++) fact.Add(fact[^1] * i); return fact[n]; }
        public static ModInt Npr(int n, int r) => Fact(n) / Fact(n - r);
        public static ModInt Ncr(int n, int r) => Fact(n) / Fact(n - r) / Fact(r);
        public static ModInt Nhr(int n, int r) => Fact(n + r - 1) / Fact(n - 1) / Fact(r);
    }

    static void Main()
    {
        int N = ReadInt;
        Queue<int>[] queues = new Queue<int>[N];

        for (int i = 0; i < N; i++)
        {
            int[] v = ReadInts;

            queues[i] = new Queue<int>();

            for (int j = 0; j < N-1; j++)
            {
                queues[i].Enqueue(v[j]-1);
            }
        }


        int count = 0;
        HashSet<int> prev = new HashSet<int>();

        for (int i = 0; i < N; i++)
        {
            prev.Add(i);
        }

        while (true)
        {
            HashSet<int> last = new HashSet<int>();
            foreach (int player in prev)
            {
                if (queues[player].Count == 0) continue;
                int opponent = queues[player].Peek();
                if (last.Contains(player) || last.Contains(opponent)) continue;
                if (queues[opponent].Peek() == player)
                {
                    queues[player].Dequeue();
                    queues[opponent].Dequeue();

                    last.Add(player);
                    last.Add(opponent);
                }

            }

            prev = last;
            if (last.Count == 0) break;
            count++;
        }

        foreach (var item in queues)
        {
            if (item.Count != 0)
            {
                WriteLine(-1);
                return;
            }
        }
        WriteLine(count);
    }


}



Measured memory_bytes: 51716