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# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
class Program
{
	static int[] dp;
	static List<List<int>> node;
	static void Main(string[] args)
	{
			// 入力フェーズ
			//int N = Int32.Parse(Console.ReadLine());
			string[] input = Console.ReadLine().Split(' '); // N,M
			int N = Int32.Parse(input[0]);
			int M = Int32.Parse(input[1]);

			// ノード情報を作る 1-indexedにする
			node = new List<List<int>>();
			for(int i=0; i<=N; i++)
			{
				List<int> a = new List<int>();
				node.Add(a);
			}
			// エッジ情報の読み込み
			for(int i=0; i<M; i++)
			{
				input = Console.ReadLine().Split(' ');
				int x = Int32.Parse(input[0]);
				int y = Int32.Parse(input[1]);
				node[x].Add(y);
			}

			dp = new int[N+1]; // dpテーブル
			// 頂点iから伸びる経路の最大の長さ
			for(int i=0; i<=N; i++)
			{
				dp[i] = -1; // -1で初期化する
			}

			int longestPath = 0; // 最大の長さの経路をメモ
			for(int i=1; i<=N; i++)
			{
				// 各ノードから伸びる経路の最大の長さを求めて行く
				longestPath = Math.Max(longestPath, getLongestPath(i));
			}
			Console.WriteLine(longestPath + "");
    }

		static int getLongestPath(int i)
		{
			// 頂点iからの経路の最大の長さを返す
			// iから伸びる頂点がなければ0を返す
			if(node[i].Count == 0)
			{
				dp[i] = 0;
				return 0;
			}

			if(dp[i] != -1)
			{
				// すでに定まっているので返す
				return dp[i];
			}
			else
			{
				// iから伸びている頂点から伸びる最大の経路 + 1を返す
				int ret = 0;
				for(int j=0; j<node[i].Count; j++)
				{
					int k = node[i][j];
					// 行き先の経路長がすでに定まっていたらそれを使う
					if(dp[k]>=0)
					{
						ret = Math.Max(ret, dp[k] + 1);
					}
					else
					{
					  ret = Math.Max(ret, getLongestPath(k) + 1);
					}
				}
				return ret;
			}
		}
}