using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    using System;
    using System.Linq;

    using Match = System.Int32;

    class Program
    {
        static readonly int PLAYER_ID_BASE = 10000;
        static Dictionary<Match, List<Match>> PreMatches = new Dictionary<Match, List<Match>>();
        static Dictionary<Match, List<Match>> PostMatches = new Dictionary<Match, List<Match>>();
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine());
            // スペース区切りの整数の入力
            List<int[]> inputs = new List<int[]>();
            for(int i = 0; i < n; i++)
            {
                inputs.Add(Console.ReadLine().Split(' ').Select(s => int.Parse(s)).ToArray());
            }

            // 循環参照判定用
            Dictionary<Match, bool> reachedMatches = new Dictionary<Match, bool>();

            // 最長パス探索用
            Dictionary<Match, int> depthOfMatches = new Dictionary<Match, int>();

            // PreMatches と PostMatches と循環参照判定用の Dictionary の初期化
            for (int i = 1; i <= n; i++)
            {
                for (int j = i + 1; j <= n; j++)
                {
                    Match tmpMatch = GetMatchId(i, j);
                    PreMatches[tmpMatch] = new List<Match>();
                    PostMatches[tmpMatch] = new List<Match>();
                    reachedMatches[tmpMatch] = false;
                    depthOfMatches[tmpMatch] = -1;
                }
            }

            // 選手 i の j 番目の要求について前後の値を確認し、 pre と post に設定する。
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n - 1; j++)
                {
                    Match thisMatch = GetMatchId(i + 1, inputs[i][j]);
                    if (j > 0)
                    {
                        Match PreMatch = GetMatchId(i + 1, inputs[i][j - 1]);
                        PreMatches[thisMatch].Add(PreMatch);
                    }
                    if (j < n - 2)
                    {
                        Match PostMatch = GetMatchId(i + 1, inputs[i][j + 1]);
                        PostMatches[thisMatch].Add(PostMatch);
                    }
                }
            }

            //// 第一引数は何でも良い？
            //bool isFeasible = IsAcyclicDFSForward(GetMatchId(1, 2), reachedMatches);
            //// reachedMatches を初期化
            //Console.ReadLine();
            //for (int i = 1; i <= n; i++)
            //{
            //    for (int j = i + 1; j <= n; j++)
            //    {
            //        Match tmpMatch = GetMatchId(i, j);
            //        reachedMatches[tmpMatch] = false;
            //    }
            //}
            //isFeasible = isFeasible && IsAcyclicDFSBackward(GetMatchId(1, 2), reachedMatches);

            // トポロジカルソート風
            Dictionary<Match, int> preNumbers = PreMatches.ToDictionary(v => v.Key, v => v.Value.Count());
            List<Match> sources = preNumbers.Where(v => v.Value == 0).Select(v => v.Key).ToList();
            List<Match> sortedMatches = new List<Match>();
            while (sources.Count() > 0)
            {
                // Console.WriteLine("sources : [ " + string.Join(" ", sources.Select(v => v.ToString())) + " ]");
                // Console.WriteLine("sorteds : [ " + string.Join(" ", sortedMatches.Select(v => v.ToString())) + " ]");
                Match topMatch = sources[0];
                sources.RemoveAt(0);
                PostMatches[topMatch].ForEach(v => {
                    preNumbers[v]--;
                    if (preNumbers[v] == 0)
                    {
                        sources.Add(v);
                    }
                    });
                sortedMatches.Add(topMatch);
            }

            // n 頂点が全てトポロジカルソートされたら、条件を満たす日程を組める。
            bool isFeasible = sortedMatches.Count() == (n * (n - 1)) / 2;
            if (!isFeasible)
            {
                Console.WriteLine("-1");
                return;
            }

            // 最長経路の探索（全試合を行うために何日必要かに相当）
            int RequiredDays = 0;
            for(int i = 1; i <= n; i++)
            {
                for(int j = i + 1; j <= n; j++)
                {
                    RequiredDays = Math.Max(RequiredDays, MaxDepthOf(GetMatchId(i, j), depthOfMatches));
                }
            }

            //出力
            Console.WriteLine(RequiredDays.ToString());
            // Console.ReadLine();
        }

        static Match GetMatchId(int player1ID, int player2ID)
        {
            return Math.Min(player1ID, player2ID) * PLAYER_ID_BASE + Math.Max(player1ID, player2ID);
        }

        static bool IsAcyclicDFSForward(Match current, Dictionary<Match, bool> reachedMatches)
        {
            Console.WriteLine(current.ToString() + " : [ " + string.Join(" ", reachedMatches.Values.Select(v => v?"1" : "_")) + " ]");
            if (reachedMatches[current]) return false;
            reachedMatches[current] = true;
            List<Match> nextMatches = PostMatches[current];
            Console.WriteLine(current.ToString() + " -> " + string.Join(" ", nextMatches));
            return nextMatches.Aggregate(true, (result, next) => result && IsAcyclicDFSForward(next, reachedMatches));
        }

        static bool IsAcyclicDFSBackward(Match current, Dictionary<Match, bool> reachedMatches)
        {
            if (reachedMatches[current]) return false;
            reachedMatches[current] = true;
            List<Match> nextMatches = PreMatches[current];
            return nextMatches.Aggregate(true, (result, next) => result && IsAcyclicDFSBackward(next, reachedMatches));
        }

        static int MaxDepthOf(Match target, Dictionary<Match, int> depthOfMatches)
        {
            if (depthOfMatches[target] < 0)
            {
                List<Match> nextMatches = PreMatches[target];
                depthOfMatches[target] = nextMatches.Aggregate(0, (result, next) => Math.Max(result, MaxDepthOf(next, depthOfMatches))) + 1;
            }
            return depthOfMatches[target];
        }
    }

    class MatchOrder
    {
        Match PreMatch { get; set; }
        Match PostMatch { get; set; }
    }
}


Measured memory_bytes: 189396