//For higher stack size use g++ -O2 -std=c++11 -Wall -Wl,--stack=268435456 a.cpp -o a.exe in cmd
    #include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstring>
    #include <chrono>
    #include <complex>
    #define ll long long
    #define ld long double
    #define vi vector<int>
    #define vll vector<ll>
    #define vvi vector < vi >
    #define pii pair<int,int>
    #define pll pair<long long, long long>
    #define mod 1000000007
    #define inf 1000000000000000001;
    #define all(c) c.begin(),c.end()
    #define mp(x,y) make_pair(x,y)
    #define mem(a,val) memset(a,val,sizeof(a))
    #define eb emplace_back
    #define pb push_back
    #define f first
    #define s second
    
    using namespace std;

    set<pii> st[1001];

    // https://www.geeksforgeeks.org/topological-sorting-indegree-based-solution/


    // Class to represent a graph 
class Graph 
{ 
    int V;    // No. of vertices' 
  
    // Pointer to an array containing adjacency listsList 
    list<int> *adj; 
  
public: 
    Graph(int V);   // Constructor 
  
    // function to add an edge to graph 
    void addEdge(int u, int v); 
  
    // prints a Topological Sort of the complete graph 
    void topologicalSort(); 
}; 
  
Graph::Graph(int V) 
{ 
    this->V = V; 
    adj = new list<int>[V]; 
} 
  
void Graph::addEdge(int u, int v) 
{ 
    adj[u].push_back(v); 
} 
  
// The function to do Topological Sort. 

int flag=0,ans;

void Graph::topologicalSort() 
{ 
    // Create a vector to store indegrees of all 
    // vertices. Initialize all indegrees as 0. 
    vector<int> in_degree(V, 0); 
    int maxi=0;
  
    // Traverse adjacency lists to fill indegrees of 
    // vertices.  This step takes O(V+E) time 
    for (int u=0; u<V; u++) 
    { 
        list<int>::iterator itr; 
        for (itr = adj[u].begin(); itr != adj[u].end(); itr++) 
             in_degree[*itr]++; 
    } 
  
    // Create an queue and enqueue all vertices with 
    // indegree 0 
    queue<pii> q; 
    for (int i = 0; i < V; i++) 
        if (in_degree[i] == 0) 
            q.push({i,1}); 
  
    // Initialize count of visited vertices 
    int cnt = 0; 
  
    // Create a vector to store result (A topological 
    // ordering of the vertices) 
    vector <int> top_order; 
  
    // One by one dequeue vertices from queue and enqueue 
    // adjacents if indegree of adjacent becomes 0 
    while (!q.empty()) 
    { 
        // Extract front of queue (or perform dequeue) 
        // and add it to topological order 
        pii x = q.front();
        int u = x.f; 
        //cout<<u<<" "<<x.s<<endl;
        maxi=max(maxi,x.s);
        q.pop(); 
        top_order.push_back(u); 
  
        // Iterate through all its neighbouring nodes 
        // of dequeued node u and decrease their in-degree 
        // by 1 
        list<int>::iterator itr; 
        //cout<<u<<endl;
        for (itr = adj[u].begin(); itr != adj[u].end(); itr++) 
  
            // If in-degree becomes zero, add it to queue 
            //cout<<u<<" "<<*itr<<" "<<in_degree[*itr]<<endl;
            if (--in_degree[*itr] == 0) 
                q.push({*itr,x.s+1}); 
  
        cnt++; 
    } 
  
    // Check if there was a cycle 
    if (cnt != V) 
    { 
        ans=-1;
        return; 
    } 
  
    // Print topological order 
    ans=maxi;
} 
    int ar[1001][1001];
    int main()
    {
        std::ios::sync_with_stdio(false);
        int T;
        T=1;
        // cin.ignore(); must be there when using getline(cin, s)
        while(T--)
        {
            int n,i,j,x,k;
            cin>>n;
            
            for(i=1;i<=n;++i)
            {
                for(j=1;j<=n-1;++j)
                {
                    cin>>ar[i][j];

                    st[i].insert({ar[i][j],j});
                }
            }
            Graph g(n*(n-1));
            //cout<<n*(n-1)<<endl;
            for(i=1;i<=n;++i)
            {
                for(j=1;j<=n-1;++j)
                {
                    auto it=st[ar[i][j]].lower_bound({i,0});
                    x=it->s;
                    //cout<<i<<":::"<<j<<endl;
                    if(x==1)
                        ;
                    else
                    {
                        //cout<<(ar[i][j]-1)*(n-1)+x-2<<".."<<(i-1)*(n-1)+j-1<<endl;
                        g.addEdge((ar[i][j]-1)*(n-1)+x-2,(i-1)*(n-1)+j-1);
                    }
                    if(j!=1)
                    {
                        //cout<<(i-1)*(n-1)+j-2<<"####"<<(i-1)*(n-1)+j-1<<endl;
                        g.addEdge((i-1)*(n-1)+j-2,(i-1)*(n-1)+j-1);
                    }
                }
            }
            //cout<<"HAI"<<endl;
            g.topologicalSort();
            cout<<ans<<endl;
        }
        return 0;
    }


Measured memory_bytes: 138352