Problem:
Score : 100 points

Problem Statement

There is a directed graph G with N vertices and M edges.
The vertices are numbered 1, 2, \ldots, N, and for each i (1 \leq i \leq M), the i-th directed edge goes from Vertex x_i to y_i.
G does not contain directed cycles.

Find the length of the longest directed path in G.
Here, the length of a directed path is the number of edges in it.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq x_i, y_i \leq N

All pairs (x_i, y_i) are distinct.

G does not contain directed cycles.

Input

Input is given from Standard Input in the following format:

N M
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the length of the longest directed path in G.

Sample Input 1

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

Sample Output 1

3

The red directed path in the following figure is the longest:

Sample Input 2

6 3
2 3
4 5
5 6

Sample Output 2

2

The red directed path in the following figure is the longest:

Sample Input 3

5 8
5 3
2 3
2 4
5 2
5 1
1 4
4 3
1 3

Sample Output 3

3

The red directed path in the following figure is one of the longest:

Solution in C# (.NET Core 3.1.201) (judge verdict: Runtime Error)

using System;
using System.Collections.Generic;

public class Graph
{
  private List<int>[] _edges;

  public Graph(int numberOfNodes)
  {
    _edges = new List<int>[numberOfNodes + 1]; // ignore index 0 for simplicity.
    for (int i = 1; i <= numberOfNodes; i++)
    {
      _edges[i] = new List<int>();
    }
  }

  public List<int> GetDestinationsOf(int node)
  {
    return _edges[node];
  }

  public void AddEdge(int fromNode, int toNode)
  {
    _edges[fromNode].Add(toNode);
  }
}

public static class Solution
{
  private static int[,] s_memo;

  public static void Main()
  {
    string[] s = Console.ReadLine().Split(' ');
    int numberOfNodes = int.Parse(s[0]);
    int numberOfEdges = int.Parse(s[1]);
    var graph = new Graph(numberOfNodes);
    for (int i = 0; i < numberOfEdges; i++)
    {
      string[] edge = Console.ReadLine().Split(' ');
      graph.AddEdge(int.Parse(edge[0]), int.Parse(edge[1]));
    }
    s_memo = new int[numberOfNodes + 1, numberOfNodes + 1]; // ignore index 0
    for (int i = 1; i <= numberOfNodes; i++)
    {
      for (int j = 1; j <= numberOfNodes; j++)
      {
        s_memo[i, j] = -1;
      }
    }
    int max = int.MinValue;
    for (int i = 1; i <= numberOfNodes; i++)
    {
      for (int j = 1; j <= numberOfNodes; j++)
      {
        int temp = GetLongestPath(i, j, graph);
        if (temp > max) max = temp;
      }
    }
    Console.WriteLine(max);
  }

  private static int GetLongestPath(int fromNode, int toNode, Graph graph)
  {
    if (fromNode == toNode) return  0;
    if (s_memo[fromNode, toNode] != -1) return s_memo[fromNode, toNode];

    int max = int.MinValue;
    List<int> availableDestinations = graph.GetDestinationsOf(fromNode);
    foreach (int destination in availableDestinations)
    {
      int temp = GetLongestPath(destination, toNode, graph);
      if (temp > max) max = temp;
    }
    return s_memo[fromNode, toNode] = (1 + max);
  }
}