Problem:
Score : 500 points

Problem Statement

N players will participate in a tennis tournament. We will call them Player 1, Player 2, \ldots, Player N.

The tournament is round-robin format, and there will be N(N-1)/2 matches in total.
Is it possible to schedule these matches so that all of the following conditions are satisfied? If the answer is yes, also find the minimum number of days required.

Each player plays at most one matches in a day.

Each player i (1 \leq i \leq N) plays one match against Player A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} in this order.

Constraints

3 \leq N \leq 1000

1 \leq A_{i, j} \leq N

A_{i, j} \neq i

A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} are all different.

Input

Input is given from Standard Input in the following format:

N
A_{1, 1} A_{1, 2} \ldots A_{1, N-1}
A_{2, 1} A_{2, 2} \ldots A_{2, N-1}
:
A_{N, 1} A_{N, 2} \ldots A_{N, N-1}

Output

If it is possible to schedule all the matches so that all of the conditions are satisfied, print the minimum number of days required; if it is impossible, print -1.

Sample Input 1

3
2 3
1 3
1 2

Sample Output 1

3

All the conditions can be satisfied if the matches are scheduled for three days as follows:

Day 1: Player 1 vs Player 2

Day 2: Player 1 vs Player 3

Day 3: Player 2 vs Player 3

This is the minimum number of days required.

Sample Input 2

4
2 3 4
1 3 4
4 1 2
3 1 2

Sample Output 2

4

All the conditions can be satisfied if the matches are scheduled for four days as follows:

Day 1: Player 1 vs Player 2, Player 3 vs Player 4

Day 2: Player 1 vs Player 3

Day 3: Player 1 vs Player 4, Player 2 vs Player 3

Day 4: Player 2 vs Player 4

This is the minimum number of days required.

Sample Input 3

3
2 3
3 1
1 2

Sample Output 3

-1

Any scheduling of the matches violates some condition.

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

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);
    }
}