#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace __gnu_pbds;
using namespace std;
#define int long long
//for set
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;   
// for multiset
typedef tree<
pair<int, int>,
null_type,
less<pair<int, int>>,
rb_tree_tag,
tree_order_statistics_node_update> ordered_multiset;


#define ff first
#define ss second
#define endl "\n"
#define all(x) (x).begin(), (x).end()
#define PI 3.1415926535897932384626433832795
int MOD=1e9+7;
int powmod(int a,int l, int md){int res=1;while(l){if(l&1)res=res*a%md;l/=2;a=a*a%md;}return res;}
typedef long long ll; typedef vector<ll> vi; typedef pair<ll, ll> ii; typedef vector<ii> vii;
#define pb push_back
int __set(int b, int i) {return b|(1<<i);} //set ith bit
int __unset(int b, int i) {return b&!(1<<i);}
int __check(int b, int i) {return b&(1<<i);} //returns 0 if ith bit is 0
int mul(int a, int b) {return ((a%MOD)*(b%MOD))%MOD;}
int add(int a, int b) {return (a+b)%MOD;}
int sub(int a, int b) {return (((a-b)%MOD)+MOD)%MOD;}
int __div(int a, int b) {return mul(a, powmod(b, MOD-2, MOD));} //if MOD is prime;
const ll inf = 0xFFFFFFFFFFFFFFFL; //very large number
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > pq; //for min priority_queue
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
clock_t time_p=clock();
void time()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}
// bool cmp(int a, int b) {
// 	return order[a] < order[b];
// }
int dfs(int u, vi& height, vector<vi>& adj) {
	// height[u]=h;
	int mx=0;
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(height[v]==-1) {
			mx = max(mx, dfs(v, height, adj));
			// mx=max(mx, height[v]);
		} else {
			mx=max(mx, height[v]);
		}
	}
	height[u]=mx+1;
	return mx+1;
}
void check(int u, vi& vis, vector<vi>& adj, int* cyc) {
	vis[u]=1;
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(!vis[v]) {
			check(v, vis, adj, cyc);
		} else if(vis[u]==1 && vis[v]==1) {
			*cyc=1;
		}
	}
	vis[u]=2;
}
int32_t main(void)
{
	IOS;
	int n; cin>>n;
	int day=0;
	vector<vi> adjlist(n);
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < n-1; j++) {
			int v; cin>>v;
			adjlist[i].pb(v-1);
		}
	}
	vector<vi> adj(n*n);
	for(int i = 0; i < n; i++) {
		for(int j = 1; j < n-1; j++) {
			int c2=min(i, adjlist[i][j])*n+max(i, adjlist[i][j]);
			int c1=min(i, adjlist[i][j-1])*n+max(i, adjlist[i][j-1]);
			adj[c1].pb(c2);
		}
	}
	int ind[n*n]={};
	for(int i = 0; i < n*n; i++) {
		for(int j = 0; j < adj[i].size(); j++) {
			ind[adj[i][j]]++;
		}
	}
	vi vis(n*n, 0);
	int cyc=0;
	for(int i = 0; i < n*n; i++) {
		check(i, vis, adj, &cyc);
	}
	if(cyc) {
		cout<<-1<<endl;
		return 0;
	}
	// int ans=0;
	// queue<pair<int,int>> q;
	// for(int i = 0; i < n*n; i++) {
	// 	if(!ind[i]) q.push({i, 0});
	// }
	// vi vis(n, 0)
	// while(!q.empty()) {
	// 	ii p = q.top(); q.pop();

	// }
	vi height(n*n, -1);
	int ans=0;
	for(int i = 0; i < n*n; i++) {
		if(ind[i]==0) {
			ans=max(ans,dfs(i, height, adj));
			// ans=max(ans, height[i]);
		}
	}
	cout<<ans<<endl;
	time();
	return 0;
}

Measured memory_bytes: 70912