import java.io._
import java.util.StringTokenizer
import scala.util.control.Breaks.{breakable,break}
import scala.collection.mutable.{Map, Queue, PriorityQueue}

object Main extends App {
  val in = new InputReader(System.in)
  val pw = new PrintWriter(System.out)

  val N = in.next().toInt
  val A = Array.ofDim[Int](N+1, N+1)
  for (y <- 1 to N; x <- 1 to N-1) {
    A(y)(x) = in.next().toInt
  }



  //
  var ans = 0L
  val inds = Array.fill[Int](N+1)(1)
  breakable {
    while(true) {
      val dp = new Array[Boolean](N+1)
      var flag = true

      for (i <- 1 to N) {
        val x = inds(i)
        if (!dp(i) && x < N) {
          val target = A(i)(x)
          val targeti = inds(target)
          if (!dp(target) && targeti < N && A(target)(targeti) == i) {
            dp(i) = true
            dp(target) = true

            inds(i) += 1
            inds(target) += 1

            if(flag)
              flag = false
          }
        }
      }

      if (flag) {
        if(inds.slice(1, N+1).forall(_ == N)) // clear
          break
        else {
          ans = -1
          break
        }
      }

      ans += 1
//      println(dp.deep)
    }
  }

//  println(inds.deep)

  println(ans)


}


class InputReader(stream: InputStream) {
  private val reader = new BufferedReader(new InputStreamReader(stream))
  private var tokenizer: StringTokenizer = new StringTokenizer(reader.readLine())
  def next(): String = {
    while (!tokenizer.hasMoreTokens()) {
      tokenizer = new StringTokenizer(reader.readLine())
    }
    tokenizer.nextToken()
  }
}
