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

class MainClass : Scanner
{
    static int N;
    static Graph<int> G;
    static void Main()
    {
        N = RInt();
        var A = new int[N][];
        for (int i = 0; i < N; i++)
        {
            A[i] = RInts();
        }

        var conv = new IndexConverter<(int, int)>();
        G = new Graph<int>(N*N);
        var Degrees = new int[N * N];
        for (int i = 0; i < N; i++)
        {
            var last = (i+1,A[i][0]);
            if (last.Item1 > last.Item2) last = (last.Item2, last.Item1);
            for (int j = 1; j < N-1; j++)
            {
                var pair = (i+1, A[i][j]);
                if (pair.Item1 > pair.Item2) pair = (pair.Item2, pair.Item1);
                conv.Add(pair);
                conv.Add(last);
                G.Add(conv.GetIndex(last), conv.GetIndex(pair));
                Degrees[conv.GetIndex(pair)]+=1;

                last = pair;
            }
        }
        
        if (TopologicalSort.Topologicalsort(G, Degrees) == null)
        {
            WriteLine(-1);return;
        }

        pdist = new int[N * N];
        mdist = new int[N * N];
        for (int i = 0; i < N*N; i++)
        {
            if (Degrees[i] == 0&&pdist[i]==0)
            {
                
                DFS(i, 1);
            }
        }
        WriteLine(mdist.Max());
    }

    static int[] pdist;
    static int[] mdist;
    static int DFS(int now,int count)
    {
        if (G[now].Count == 0)
        {
            mdist[now] = count;
            return count;
        }

        int max = 0;
        foreach (var item in G[now])
        {
            if (pdist[item] > 0)
            {
                max = Max(max, mdist[item] - pdist[item] + count + 1);
                continue;
            }
            pdist[item] = count + 1;
            max = Max(DFS(item, count + 1), max);
        }
        mdist[now] = max;
        return max;
    }
}

static class TopologicalSort
{
    //Degreesはその頂点にのびる辺の数 無理ならnullを返す
    public static List<int> Topologicalsort(Graph<int> G, int[] Degrees)
    {

        var que = new Queue<int>();
        for (int i = 0; i < Degrees.Length; i++)
        {
            if (Degrees[i] == 0)
                que.Enqueue(i);
        }

        var sorted = new List<int>();
        while (que.Count > 0)
        {
            var v = que.Dequeue();
            sorted.Add(v);
            foreach (var i in G[v])
            {
                Degrees[i]--;
                if (Degrees[i] == 0)
                    que.Enqueue(i);
            }
        }
        if (Degrees.Length != sorted.Count) return null;
        return sorted;
    }
}

class IndexConverter<T> //文字列など 数の順列に変換する。
{
    static Dictionary<T, int> itemToIndex = new Dictionary<T, int>();
    static List<T> indexToItem = new List<T>();

    public T GetItem(int i) => indexToItem[i];
    public int GetIndex(T item) => itemToIndex[item];
    public void Add(T item)
    {
        if (itemToIndex.ContainsKey(item)) return;

        itemToIndex[item] = itemToIndex.Count;
        indexToItem.Add(item);
    }
}
class Graph<T>
{
    private List<T>[] G;
    public Graph(int size)
    {
        G = new List<T>[size];
        for (int i = 0; i < size; i++)
        {
            G[i] = new List<T>();
        }
    }

    public List<T> this[int i] => G[i];
    public void Add(int from, T to) => G[from].Add(to);
    public List<T>[] ToListArray() => G;
    public int Length => G.Length;
}

class Scanner
{
    public static string RString() => Console.ReadLine();
    public static int RInt() => ReadTuple<int>();
    public static long RLong() => ReadTuple<long>();
    public static double RDouble() => ReadTuple<double>();

    public static string[] RStrings() => Console.ReadLine().Split();
    public static int[] RInts() => Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
    public static long[] RLongs() => Array.ConvertAll(Console.ReadLine().Split(), long.Parse);
    public static double[] RDoubles() => Array.ConvertAll(Console.ReadLine().Split(), double.Parse);
    public static int[] RInts(Func<string, int> func) => Console.ReadLine().Split().Select(func).ToArray();
    public static long[] RLongs(Func<string, long> func) => Console.ReadLine().Split().Select(func).ToArray();
    public static double[] RDoubles(Func<string, double> func) => Console.ReadLine().Split().Select(func).ToArray();
    //public static string[] RStrings(Func<string, string> func) => Console.ReadLine().Split().Select(func).ToArray();

    public static T1 ReadTuple<T1>()
    {
        var r = RString();
        var r1 = (T1)Convert.ChangeType(r, typeof(T1));
        return r1;
    }
    public static (T1, T2) ReadTuple<T1, T2>()
    {
        var r = RStrings();
        var r1 = (T1)Convert.ChangeType(r[0], typeof(T1));
        var r2 = (T2)Convert.ChangeType(r[1], typeof(T2));
        return (r1, r2);
    }
    public static (T1, T2, T3) ReadTuple<T1, T2, T3>()
    {
        var r = RStrings();
        var r1 = (T1)Convert.ChangeType(r[0], typeof(T1));
        var r2 = (T2)Convert.ChangeType(r[1], typeof(T2));
        var r3 = (T3)Convert.ChangeType(r[2], typeof(T3));
        return (r1, r2, r3);
    }
    public static (T1, T2, T3, T4) ReadTuple<T1, T2, T3, T4>()
    {
        var r = RStrings();
        var r1 = (T1)Convert.ChangeType(r[0], typeof(T1));
        var r2 = (T2)Convert.ChangeType(r[1], typeof(T2));
        var r3 = (T3)Convert.ChangeType(r[2], typeof(T3));
        var r4 = (T4)Convert.ChangeType(r[3], typeof(T4));
        return (r1, r2, r3, r4);
    }
}


Measured memory_bytes: 145688