Problem:
Score : 500 points

Problem Statement

N players will participate in a tennis tournament. We will call them Player 1, Player 2, \ldots, Player N.

The tournament is round-robin format, and there will be N(N-1)/2 matches in total.
Is it possible to schedule these matches so that all of the following conditions are satisfied? If the answer is yes, also find the minimum number of days required.

Each player plays at most one matches in a day.

Each player i (1 \leq i \leq N) plays one match against Player A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} in this order.

Constraints

3 \leq N \leq 1000

1 \leq A_{i, j} \leq N

A_{i, j} \neq i

A_{i, 1}, A_{i, 2}, \ldots, A_{i, N-1} are all different.

Input

Input is given from Standard Input in the following format:

N
A_{1, 1} A_{1, 2} \ldots A_{1, N-1}
A_{2, 1} A_{2, 2} \ldots A_{2, N-1}
:
A_{N, 1} A_{N, 2} \ldots A_{N, N-1}

Output

If it is possible to schedule all the matches so that all of the conditions are satisfied, print the minimum number of days required; if it is impossible, print -1.

Sample Input 1

3
2 3
1 3
1 2

Sample Output 1

3

All the conditions can be satisfied if the matches are scheduled for three days as follows:

Day 1: Player 1 vs Player 2

Day 2: Player 1 vs Player 3

Day 3: Player 2 vs Player 3

This is the minimum number of days required.

Sample Input 2

4
2 3 4
1 3 4
4 1 2
3 1 2

Sample Output 2

4

All the conditions can be satisfied if the matches are scheduled for four days as follows:

Day 1: Player 1 vs Player 2, Player 3 vs Player 4

Day 2: Player 1 vs Player 3

Day 3: Player 1 vs Player 4, Player 2 vs Player 3

Day 4: Player 2 vs Player 4

This is the minimum number of days required.

Sample Input 3

3
2 3
3 1
1 2

Sample Output 3

-1

Any scheduling of the matches violates some condition.

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#include <cstring>
#include <stack>
#include <algorithm>

const long long int INFTY = 1e9;

long long int maximum_path(long long int N, std::vector<std::vector<long long int> > &G, std::vector<long long int> &dp_table, /*std::vector<long long int> &reached_table, */long long int start, long long int original_start);
long long int game_id(long long int N, long long int player1, long long int player2);

int topological_sort(std::vector<std::vector<long long int> > &G, long long int V, std::vector<long long int> &sorted_index);


int main(){
  
  // read problem
  long long int N, tmp1, tmp2;
  scanf("%lld", &N);
  std::vector<std::vector<long long int> > G(N*N);
  
  for(long long int i = 0; i < N; i++){
    scanf("%lld", &tmp1);
    for(long long int j = 0; j < N-2; j++){
      tmp2 = tmp1;
      scanf("%lld", &tmp1);
      G[game_id(N, i, tmp2-1)].push_back(game_id(N, i, tmp1-1));
      //std::cerr << "edge from " << game_id(N, i, tmp2-1) << " to " << game_id(N, i, tmp1-1) << std::endl;
    }
  }
  
  // check closed loop
  std::vector<long long int> sorted_index;
  int result = topological_sort(G, N*N, sorted_index);
  if(result == 1){
    std::cout << -1 << std::endl;
    return 0;
  }
  
  /************************************************************************/
  
  // solve problem
  std::vector<long long int> dp_table/*, reached_table*/;
  for(long long int i = 0; i < N*N; i++){
    dp_table.push_back(-1);
    //reached_table.push_back(-1);
  }
  
  long long int ans = 0;
  for(long long int i = 0; i < N; i++){
    ans = std::max(ans, maximum_path(N, G, dp_table, /*reached_table,*/ i, i));
    //std::cerr << "ahaha" << i << " "<< ans  << std::endl;
  }
  
  std::cerr << "Answer: " << std::endl;
  if(ans >= INFTY){
    std::cout << "-1" << std::endl;
  }
  else{
    std::cout << ans+1 << std::endl;
  }
  
  return 0;
}

long long int maximum_path(long long int N, std::vector<std::vector<long long int> > &G, std::vector<long long int> &dp_table, /*std::vector<long long int> &reached_table, */long long int start, long long int original_start){
  
  // if the point have been already tested
  if(dp_table[start] >= 0){
    return dp_table[start];
  }
  // if there is no path starting from start
  if(G[start].size() == 0){
    dp_table[start] = 0;
    return 0;
  }
  // if there are edges starting from start
  else{
    long long int tmp = 0;
    for(long long int i = 0; i < G[start].size(); i++){
      if(G[start][i] == original_start){
        return INFTY;
      }
      else{
        tmp = std::max(tmp, maximum_path(N, G, dp_table, /*reached_table,*/ G[start][i],original_start)+1);
      }
    }
    dp_table[start] = tmp;
    return tmp;
  }
}

long long int game_id(long long int N, long long int player1, long long int player2){
  if(player1 < player2){
    return player1*N + player2;
  }
  else{
    return player2*N + player1;
  }
}

int topological_sort(std::vector<std::vector<long long int> > &G, long long int V, std::vector<long long int> &sorted_index){
  
  // clear sorted_index
  sorted_index.clear();
  
  // calculate in_degree
  std::vector<long long int> in_degree(V);

  for(long long int i = 0; i < V; i++){
    for(long long int j = 0; j < G[i].size(); j++){
      in_degree[G[i][j]]++;
    }
  }
  
  // calculate topological sort
  std::stack<long long int> stack;
  for(long long int i = 0; i < V; i++){
    if(in_degree[i] == 0){
      stack.push(i);
    }
  }
  
  long long int tmp_vertex;
  while(!stack.empty()){
    // get vertex with zero in-degree
    tmp_vertex = stack.top();
    stack.pop();
    // push vertex to sorted_index
    sorted_index.push_back(tmp_vertex);
    // update state
    for(long long int i = 0; i < G[tmp_vertex].size(); i++){
      in_degree[G[tmp_vertex][i]]--;
      if(in_degree[G[tmp_vertex][i]] == 0){
        stack.push(G[tmp_vertex][i]);
      }
    }
  }
  
  // check topological sort
  // if topological sort is carried out successfully (the given graph is DAG)
  if(sorted_index.size() == V){
    return 0;
  }
  // if topological sort failed (the given graph is NOT DAG)
  else{
    return 1;
  }
}