#

import sys

import time



def input(): return sys.stdin.readline().strip()



def main():

    n = int(eval(input()))

    agrid = []

    agrid_pointer = [0] * n



    start = time.time()



    for i in range(n):

        al = list(map(int, input().split()))

        agrid.append(al)



    ans = 0



    while True:

        match = set()

        for i in range(n):

            if agrid_pointer[i] == n - 1 or i in match:  # もう全部対戦済み or この日対戦済み

                continue



            target = agrid[i][agrid_pointer[i]] - 1

            if agrid_pointer[target] == n - 1 or target in match:  # もう全部対戦済み or この日対戦済み

                continue

            # i, target は対戦可能



            if agrid[target][agrid_pointer[target]] - 1 != i:

                continue



            # can match

            agrid_pointer[i] += 1

            agrid_pointer[target] += 1



            match.add(i)

            match.add(target)



            if len(match) == n or len(match) == n - 1:  # 全員試合することが決まったら

                break



        # print(match)

        if len(match) == 0:  # 対戦がなくなったら

            break

        elapsed_time = time.time() - start

        if elapsed_time > 1.5:

            print((n * (n-1)//2))

            return



        ans += 1



    # print(aconditions)

    # 対戦が残ってたら

    for p in agrid_pointer:

        if p != n - 1:

            print((-1))

            return

    print(ans)





if __name__ == '__main__':

    main()

#

import sys

from collections import deque



def input(): return sys.stdin.readline().strip()



def main():

    n = int(eval(input()))

    agrid = []

    agrid_pointer = [0] * n



    for i in range(n):

        al = list(map(int, input().split()))

        for j in range(len(al)):

            al[j] -= 1

        agrid.append(al)



    ans = 0



    def find_next(idx, q, m):

        if agrid_pointer[idx] == n - 1 or i in m:  # もう全部対戦済み or この日対戦済み

            return



        target = agrid[idx][agrid_pointer[idx]]

        if agrid_pointer[target] == n - 1 or target in m:  # もう全部対戦済み or この日対戦済み

            return



        if agrid[target][agrid_pointer[target]] != idx:

            return



        q.append((idx, target))

        m.add(idx)

        m.add(target)



    que = deque()

    first_matching = set()

    for i in range(n):

        find_next(i, que, first_matching)



    while que:

        ans += 1



        changed = []

        while que:

            i, j = que.popleft()

            agrid_pointer[i] += 1

            agrid_pointer[j] += 1

            changed.append(i)

            changed.append(j)



        next_que = deque()

        match = set()

        for i in changed:

            find_next(i, next_que, match)



        # print(match)

        que = next_que



    # print(aconditions)

    # 対戦が残ってたら

    for p in agrid_pointer:

        if p != n - 1:

            print((-1))

            return

    print(ans)





if __name__ == '__main__':

    main()

#
import sys
import time


def input():
    return sys.stdin.readline().strip()


def main():
    n = int(eval(input()))
    agrid = []
    agrid_pointer = [0] * n
    start = time.time()
    for i in range(n):
        al = list(map(int, input().split()))
        agrid.append(al)
    ans = 0
    while True:
        match = set()
        for i in range(n):
            if agrid_pointer[i] == n - 1 or i in match:  # もう全部対戦済み or この日対戦済み
                continue
            target = agrid[i][agrid_pointer[i]] - 1
            if agrid_pointer[target] == n - 1 or target in match:  # もう全部対戦済み or この日対戦済み
                continue
            # i, target は対戦可能
            if agrid[target][agrid_pointer[target]] - 1 != i:
                continue
            # can match
            agrid_pointer[i] += 1
            agrid_pointer[target] += 1
            match.add(i)
            match.add(target)
            if len(match) == n or len(match) == n - 1:  # 全員試合することが決まったら
                break
        # print(match)
        if len(match) == 0:  # 対戦がなくなったら
            break
        elapsed_time = time.time() - start
        if elapsed_time > 1.5:
            print((n * (n - 1) // 2))
            return
        ans += 1
    # print(aconditions)
    # 対戦が残ってたら
    for p in agrid_pointer:
        if p != n - 1:
            print((-1))
            return
    print(ans)


if __name__ == "__main__":
    main()

#
import sys
from collections import deque


def input():
    return sys.stdin.readline().strip()


def main():
    n = int(eval(input()))
    agrid = []
    agrid_pointer = [0] * n
    for i in range(n):
        al = list(map(int, input().split()))
        for j in range(len(al)):
            al[j] -= 1
        agrid.append(al)
    ans = 0

    def find_next(idx, q, m):
        if agrid_pointer[idx] == n - 1 or i in m:  # もう全部対戦済み or この日対戦済み
            return
        target = agrid[idx][agrid_pointer[idx]]
        if agrid_pointer[target] == n - 1 or target in m:  # もう全部対戦済み or この日対戦済み
            return
        if agrid[target][agrid_pointer[target]] != idx:
            return
        q.append((idx, target))
        m.add(idx)
        m.add(target)

    que = deque()
    first_matching = set()
    for i in range(n):
        find_next(i, que, first_matching)
    while que:
        ans += 1
        changed = []
        while que:
            i, j = que.popleft()
            agrid_pointer[i] += 1
            agrid_pointer[j] += 1
            changed.append(i)
            changed.append(j)
        next_que = deque()
        match = set()
        for i in changed:
            find_next(i, next_que, match)
        # print(match)
        que = next_que
    # print(aconditions)
    # 対戦が残ってたら
    for p in agrid_pointer:
        if p != n - 1:
            print((-1))
            return
    print(ans)


if __name__ == "__main__":
    main()

-import time +from collections import deque -    start = time.time() +        for j in range(len(al)): +            al[j] -= 1 -    while True: + +    def find_next(idx, q, m): +        if agrid_pointer[idx] == n - 1 or i in m:  # もう全部対戦済み or この日対戦済み +            return +        target = agrid[idx][agrid_pointer[idx]] +        if agrid_pointer[target] == n - 1 or target in m:  # もう全部対戦済み or この日対戦済み +            return +        if agrid[target][agrid_pointer[target]] != idx: +            return +        q.append((idx, target)) +        m.add(idx) +        m.add(target) + +    que = deque() +    first_matching = set() +    for i in range(n): +        find_next(i, que, first_matching) +    while que: +        ans += 1 +        changed = [] +        while que: +            i, j = que.popleft() +            agrid_pointer[i] += 1 +            agrid_pointer[j] += 1 +            changed.append(i) +            changed.append(j) +        next_que = deque() -        for i in range(n): -            if agrid_pointer[i] == n - 1 or i in match:  # もう全部対戦済み or この日対戦済み -                continue -            target = agrid[i][agrid_pointer[i]] - 1 -            if agrid_pointer[target] == n - 1 or target in match:  # もう全部対戦済み or この日対戦済み -                continue -            # i, target は対戦可能 -            if agrid[target][agrid_pointer[target]] - 1 != i: -                continue -            # can match -            agrid_pointer[i] += 1 -            agrid_pointer[target] += 1 -            match.add(i) -            match.add(target) -            if len(match) == n or len(match) == n - 1:  # 全員試合することが決まったら -                break +        for i in changed: +            find_next(i, next_que, match) -        if len(match) == 0:  # 対戦がなくなったら -            break -        elapsed_time = time.time() - start -        if elapsed_time > 1.5: -            print((n * (n - 1) // 2)) -            return -        ans += 1 +        que = next_que