#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>
#include <utility>

long long mod = 1e9+7;
class Mint {
public:
  long long x;
  Mint(){}; // 引数なしでも定義できるように引数なしコンストラクタも用意しておく
  Mint(long long a){
    x = a%mod;
    while(x<0){
      x += mod;
    }
  };
  Mint& operator += (const Mint &a){
    x+=a.x;
    x%=mod;
    return *this;
  }
  Mint& operator -= (const Mint &a){
    x += (mod - a.x);
    x%=mod;
    return *this;
  }
  Mint& operator *= (const Mint &a){
    x*=a.x;
    x%=mod;
    return *this;
  }


  // a^n mod を計算する
  // Useaeg: Mint z = y.pow(y, n);
  Mint pow(Mint a, long long n) const {
    Mint y(1);
    Mint b(a);
    while (n > 0) {
     if (n & 1) y *= b;
      b *= b;
      n >>= 1;
    }
    return y;
  }

  // a^{-1} mod を計算する
  Mint modinv(const Mint &a) const {
    return pow(a, mod-2);
  }

  Mint& operator /= (const Mint &a) {
    x *= modinv(a).x;
    x %= mod;
    return *this;
  }

  Mint operator + (Mint &a) const {
    Mint y(*this);
    y += a;
    return y;
  }

  Mint operator - (Mint &a) const {
    Mint y(*this);
    y -= a;
    return y;
  }

  Mint operator * (Mint &a) const {
    Mint y(*this);
    y *= a;
    return y;
  }

  Mint operator / (Mint &a) const {
    Mint y(*this);
    y/=a;
    return y.x;
  }

  bool operator == (Mint &a) const {
    return x==a.x;
  }

  bool operator != (Mint &a) const {
    return x!=a.x;
  }
};

int main(){
  int N;
  scanf("%d", &N);
  std::queue<int> stack[1004];
  int A;
  for (int i=0; i<N; i++){
    for (int j=0; j<N-1; j++){
      scanf("%d", &A);
      A--;
      stack[i].push(A);
    };
  }
  std::vector<std::pair<int, int > > queue;
  for (int i=0; i<N; i++){
    if (stack[i].size()==0) continue;
    int op = stack[i].front();
    if (stack[op].size()>0){
      int opop = stack[op].front();
      if (opop==i){
	int min=std::min(i, op);
	int max=std::max(i, op);
	queue.push_back(std::make_pair(min, max));
      }
    }
  }
  std::sort(queue.begin(), queue.end());
  queue.erase(unique(queue.begin(), queue.end()), queue.end());
  int day = 0;
  while(queue.size()>0){
    std::vector<std::pair<int, int > > prevqueue;
    std::swap(queue, prevqueue);
    for (auto &entry : prevqueue){
      int i = entry.first;
      int j = entry.second;
      stack[i].pop();
      stack[j].pop();
      //printf("Game(%d, %d)\n", i, j);
    }
    //printf("size=%d\n", prevqueue.size());
    while(prevqueue.size()>0){
      int i = prevqueue.back().first; 
      int j = prevqueue.back().second;
      prevqueue.pop_back();
      // i
      //printf("i=%d\n", i);
      if (stack[i].size()>0){ 
	int op = stack[i].front();
	//printf("op=%d\n", op);
	if (stack[op].size()>0){
	  int opop = stack[op].front();
	  //printf("candiudate(%d, %d, %d)\n", i, op, opop);
	  if (opop==i){
	    int min=std::min(i, op);
	    int max=std::max(i, op);
	    queue.push_back(std::make_pair(min, max));
	  }
	}
      }
      // j
      if (stack[j].size()==0) continue;
      int op = stack[j].front();
      if (stack[op].size()>0){
	int opop = stack[op].front();
	//printf("candiudate(%d, %d, %d)\n", i, op, opop);
	if (opop==j){
	  int min=std::min(j, op);
	  int max=std::max(j, op);
	  queue.push_back(std::make_pair(min, max));
	}
      }
    }
    std::sort(queue.begin(), queue.end());
    queue.erase(unique(queue.begin(), queue.end()), queue.end());
    day++;
  }
  for (int i=0; i<N; i++){
    if (stack[i].size()>0) {
      printf("-1\n");
      return 0;
    }
  }
  printf("%d\n", day);
  return 0;
}


Measured memory_bytes: 7252