# -*- coding: utf-8 -*-

from collections import Counter, defaultdict





import sys

# sys.setrecursionlimit(10**6)

readline = sys.stdin.buffer.readline

# readline = sys.stdin.readline



INF = 1 << 60





def read_int():

    return int(readline())





def read_int_n():

    return list(map(int, readline().split()))





def read_float():

    return float(readline())





def read_float_n():

    return list(map(float, readline().split()))





def read_str():

    return readline().strip()





def read_str_n():

    return readline().strip().split()





def ep(*args):

    print(*args, file=sys.stderr)





def mt(f):

    import time



    def wrap(*args, **kwargs):

        s = time.perf_counter()

        ret = f(*args, **kwargs)

        e = time.perf_counter()



        ep(e - s, 'sec')

        return ret



    return wrap





@mt

def slv(N, A):

    g = defaultdict(list)

    rg = defaultdict(set)



    V = set()



    def ij2v(i, j):

        if i > j:

            i, j = j, i

        return i * 10**6 + j

    for i, a in enumerate(A, start=1):

        for j in range(len(a)-1):

            u = ij2v(i, a[j])

            v = ij2v(i, a[j+1])

            g[u].append(v)

            rg[v].add(u)

            V.add(u)

            V.add(v)



    s = []

    for v in V:

        if not rg[v]:

            s.append(v)



    done = len(s)

    ans = 0

    while s:

        ans += 1

        ns = []

        for u in s:

            for v in g[u]:

                # if v in done:

                #     continue

                rg[v].remove(u)

                if len(rg[v]) == 0:

                    ns.append(v)

                    done += 1

        s = ns



    if done != N * (N-1) // 2:

        return -1



    return ans







def main():

    N = read_int()

    A = [read_int_n() for _ in range(N)]

    print(slv(N, A))





if __name__ == '__main__':

    main()

import sys

sys.setrecursionlimit(10**6)

readline = sys.stdin.readline



MAXN = 1005

MAXV = MAXN*(MAXN-1)//2

to = [[] for _ in range(MAXV)] # 頂点間の辺の情報

id = [[[] for _ in range(MAXN)] for _ in range(MAXN)] # 試合のid=DAGの頂点番号

def toId(i,j): # 選手idから試合idを返す関数

    if i > j: # i,jが逆になっても試合idは同じ

        i,j = j,i

    return id[i][j]



visited = [False]*MAXV

calculated = [False]*MAXV

dp = [1]*MAXV # Vからスタートしたときの最長経路。頂点の個数ベースで経路の長さを数えるので、初期値は1



def dfs(v):

    if visited[v]:

        if not calculated[v]:

            return -1 # 計算が終わっていない頂点を2度訪れるのはループがあるということ

        return dp[v]

    visited[v] = True

    for u in to[v]: # 全ての辺をなめる

        res = dfs(u)

        if res == -1: return -1 # ループがあれば-1を返す

        dp[v] = max(dp[v], res+1)

    calculated[v] = True

    return dp[v]



def main():

    n = int(eval(input()))

    a = [[int(i) for i in readline().split()] for _ in range(n)]

    for i in range(n):

        for j in range(n-1):

            a[i][j] -= 1 # 選手idを0始まりに変換

    V = 0

    for i in range(n):

        for j in range(n):

            if i < j:

                id[i][j] = V

                V += 1 # 0から順に各試合にidを割り振る

    for i in range(n):

        for j in range(n-1):

            a[i][j] = toId(i,a[i][j]) # 選手idを試合id(頂点番号)に置き換える

        for j in range(n-2): # 頂点間の依存関係はn-2個

            to[a[i][j+1]].append(a[i][j])

    ans = 0

    for i in range(V):

        res = dfs(i)

        if res == -1:

            print('-1') # ループがあれば-1を返す（問題文の指示）

            return

        ans = max(ans, res)

    print(ans)

    return



if __name__ == '__main__':

    main()
# -*- coding: utf-8 -*-
from collections import Counter, defaultdict
import sys

# sys.setrecursionlimit(10**6)
readline = sys.stdin.buffer.readline
# readline = sys.stdin.readline
INF = 1 << 60


def read_int():
    return int(readline())


def read_int_n():
    return list(map(int, readline().split()))


def read_float():
    return float(readline())


def read_float_n():
    return list(map(float, readline().split()))


def read_str():
    return readline().strip()


def read_str_n():
    return readline().strip().split()


def ep(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.perf_counter()
        ret = f(*args, **kwargs)
        e = time.perf_counter()
        ep(e - s, "sec")
        return ret

    return wrap


@mt
def slv(N, A):
    g = defaultdict(list)
    rg = defaultdict(set)
    V = set()

    def ij2v(i, j):
        if i > j:
            i, j = j, i
        return i * 10**6 + j

    for i, a in enumerate(A, start=1):
        for j in range(len(a) - 1):
            u = ij2v(i, a[j])
            v = ij2v(i, a[j + 1])
            g[u].append(v)
            rg[v].add(u)
            V.add(u)
            V.add(v)
    s = []
    for v in V:
        if not rg[v]:
            s.append(v)
    done = len(s)
    ans = 0
    while s:
        ans += 1
        ns = []
        for u in s:
            for v in g[u]:
                # if v in done:
                #     continue
                rg[v].remove(u)
                if len(rg[v]) == 0:
                    ns.append(v)
                    done += 1
        s = ns
    if done != N * (N - 1) // 2:
        return -1
    return ans


def main():
    N = read_int()
    A = [read_int_n() for _ in range(N)]
    print(slv(N, A))


if __name__ == "__main__":
    main()

import sys

sys.setrecursionlimit(10**6)
readline = sys.stdin.readline
MAXN = 1005
MAXV = MAXN * (MAXN - 1) // 2
to = [[] for _ in range(MAXV)]  # 頂点間の辺の情報
id = [[[] for _ in range(MAXN)] for _ in range(MAXN)]  # 試合のid=DAGの頂点番号


def toId(i, j):  # 選手idから試合idを返す関数
    if i > j:  # i,jが逆になっても試合idは同じ
        i, j = j, i
    return id[i][j]


visited = [False] * MAXV
calculated = [False] * MAXV
dp = [1] * MAXV  # Vからスタートしたときの最長経路。頂点の個数ベースで経路の長さを数えるので、初期値は1


def dfs(v):
    if visited[v]:
        if not calculated[v]:
            return -1  # 計算が終わっていない頂点を2度訪れるのはループがあるということ
        return dp[v]
    visited[v] = True
    for u in to[v]:  # 全ての辺をなめる
        res = dfs(u)
        if res == -1:
            return -1  # ループがあれば-1を返す
        dp[v] = max(dp[v], res + 1)
    calculated[v] = True
    return dp[v]


def main():
    n = int(eval(input()))
    a = [[int(i) for i in readline().split()] for _ in range(n)]
    for i in range(n):
        for j in range(n - 1):
            a[i][j] -= 1  # 選手idを0始まりに変換
    V = 0
    for i in range(n):
        for j in range(n):
            if i < j:
                id[i][j] = V
                V += 1  # 0から順に各試合にidを割り振る
    for i in range(n):
        for j in range(n - 1):
            a[i][j] = toId(i, a[i][j])  # 選手idを試合id(頂点番号)に置き換える
        for j in range(n - 2):  # 頂点間の依存関係はn-2個
            to[a[i][j + 1]].append(a[i][j])
    ans = 0
    for i in range(V):
        res = dfs(i)
        if res == -1:
            print("-1")  # ループがあれば-1を返す（問題文の指示）
            return
        ans = max(ans, res)
    print(ans)
    return


if __name__ == "__main__":
    main()

-# -*- coding: utf-8 -*- -from collections import Counter, defaultdict -# sys.setrecursionlimit(10**6) -readline = sys.stdin.buffer.readline -# readline = sys.stdin.readline -INF = 1 << 60 +sys.setrecursionlimit(10**6) +readline = sys.stdin.readline +MAXN = 1005 +MAXV = MAXN * (MAXN - 1) // 2 +to = [[] for _ in range(MAXV)]  # 頂点間の辺の情報 +id = [[[] for _ in range(MAXN)] for _ in range(MAXN)]  # 試合のid=DAGの頂点番号 -def read_int(): -    return int(readline()) +def toId(i, j):  # 選手idから試合idを返す関数 +    if i > j:  # i,jが逆になっても試合idは同じ +        i, j = j, i +    return id[i][j] -def read_int_n(): -    return list(map(int, readline().split())) +visited = [False] * MAXV +calculated = [False] * MAXV +dp = [1] * MAXV  # Vからスタートしたときの最長経路。頂点の個数ベースで経路の長さを数えるので、初期値は1 -def read_float(): -    return float(readline()) - - -def read_float_n(): -    return list(map(float, readline().split())) - - -def read_str(): -    return readline().strip() - - -def read_str_n(): -    return readline().strip().split() - - -def ep(*args): -    print(*args, file=sys.stderr) - - -def mt(f): -    import time - -    def wrap(*args, **kwargs): -        s = time.perf_counter() -        ret = f(*args, **kwargs) -        e = time.perf_counter() -        ep(e - s, "sec") -        return ret - -    return wrap - - -@mt -def slv(N, A): -    g = defaultdict(list) -    rg = defaultdict(set) -    V = set() - -    def ij2v(i, j): -        if i > j: -            i, j = j, i -        return i * 10**6 + j - -    for i, a in enumerate(A, start=1): -        for j in range(len(a) - 1): -            u = ij2v(i, a[j]) -            v = ij2v(i, a[j + 1]) -            g[u].append(v) -            rg[v].add(u) -            V.add(u) -            V.add(v) -    s = [] -    for v in V: -        if not rg[v]: -            s.append(v) -    done = len(s) -    ans = 0 -    while s: -        ans += 1 -        ns = [] -        for u in s: -            for v in g[u]: -                # if v in done: -                #     continue -                rg[v].remove(u) -                if len(rg[v]) == 0: -                    ns.append(v) -                    done += 1 -        s = ns -    if done != N * (N - 1) // 2: -        return -1 -    return ans +def dfs(v): +    if visited[v]: +        if not calculated[v]: +            return -1  # 計算が終わっていない頂点を2度訪れるのはループがあるということ +        return dp[v] +    visited[v] = True +    for u in to[v]:  # 全ての辺をなめる +        res = dfs(u) +        if res == -1: +            return -1  # ループがあれば-1を返す +        dp[v] = max(dp[v], res + 1) +    calculated[v] = True +    return dp[v] -    N = read_int() -    A = [read_int_n() for _ in range(N)] -    print(slv(N, A)) +    n = int(eval(input())) +    a = [[int(i) for i in readline().split()] for _ in range(n)] +    for i in range(n): +        for j in range(n - 1): +            a[i][j] -= 1  # 選手idを0始まりに変換 +    V = 0 +    for i in range(n): +        for j in range(n): +            if i < j: +                id[i][j] = V +                V += 1  # 0から順に各試合にidを割り振る +    for i in range(n): +        for j in range(n - 1): +            a[i][j] = toId(i, a[i][j])  # 選手idを試合id(頂点番号)に置き換える +        for j in range(n - 2):  # 頂点間の依存関係はn-2個 +            to[a[i][j + 1]].append(a[i][j]) +    ans = 0 +    for i in range(V): +        res = dfs(i) +        if res == -1: +            print("-1")  # ループがあれば-1を返す（問題文の指示） +            return +        ans = max(ans, res) +    print(ans) +    return