import java.math.*

val MaxMatch = 499500

val Edges = Array(MaxMatch, { mutableListOf<Int>() })
val RevEdges = Array(MaxMatch, {mutableListOf<Int>() })

fun main(args: Array<String>) {
    val N = readInputLine().toInt()
    
    val A = Array(N, { readInputLine().split(" ").map { it.toInt() - 1 }.toIntArray() })
    
    val match = Array(N, { IntArray(N - 1, { -1 }) })
    
    val matchMemo = Array(N, { IntArray(N, { -1 })})
    
    var id = 0
    
    for (i in 0 until N) {
        for (j in 0 until N - 1) {
            if (matchMemo[i][A[i][j]] == -1) {
                match[i][j] = id
                matchMemo[i][A[i][j]] = id
                matchMemo[A[i][j]][i] = id
                if (j != 0) {
                    Edges[match[i][j - 1]].add(id)
                    RevEdges[id].add(match[i][j - 1])
                }
                id++
            } else {
                match[i][j] = matchMemo[i][A[i][j]]
                if (j != 0) {
                    Edges[match[i][j - 1]].add(match[i][j])
                    RevEdges[match[i][j]].add(match[i][j - 1])
                }
            }
        }
    }

    if (existsCycle()) {
        println(-1)
        return
    }

    var ans = 0

    for (i in 0 until N) {
        ans = Math.max(ans, pathLength(match[i][N - 2]))
    }

    println(ans)
}

fun readInputLine(): String {
    return readLine()!!
}

val NewState = 1
val ActiveState = 2
val FinishState = 3
val nodeStatus = IntArray(MaxMatch, { NewState })

fun existsCycle(): Boolean {
    for (v in 0 until MaxMatch) {
        if (nodeStatus[v] == NewState) {
            if (existsCycleSub(v)) {
                return true
            }
        }
    }

    return false
}

fun existsCycleSub(source: Int): Boolean {
    nodeStatus[source] = ActiveState
    
    for (e in Edges[source]) {
        if (nodeStatus[e] == ActiveState) {
            return true
        } else if (nodeStatus[e] == NewState) {
            if (existsCycleSub(e)) {
                return true
            }
        }
    }

    nodeStatus[source] = FinishState
    
    return false
}

val lengthMemo = IntArray(MaxMatch)

fun pathLength(id: Int): Int {
    if (lengthMemo[id] == 0) {
        var length = 1
        
        for (e in RevEdges[id]) {
            length = Math.max(length, pathLength(e) + 1)
        }
        
        lengthMemo[id] = length
    }

    return lengthMemo[id]
}
