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 Kotlin (1.0.0) (judge verdict: Accepted)

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*

fun main(omkar: Array<String>) {
    val jin = BufferedReader(InputStreamReader(System.`in`))
    var line = jin.readLine()
    var six = line.indexOf(' ')
    val n = line.substring(0, six).toInt()
    val m = line.substring(six + 1).toInt()
    val rev = Array(n + 1) { mutableListOf<Int>() }
    for (j in 1..m) {
        line = jin.readLine()
        six = line.indexOf(' ')
        val a = line.substring(0, six).toInt()
        val b = line.substring(six + 1).toInt()
        rev[b].add(a)
    }
    val dp = IntArray(n + 1) { -2 }
    val stack = Stack<Int>()
    for (j in 1..n) {
        stack.push(j)
    }
    var answer = 0
    while (stack.isNotEmpty()) {
        val a = stack.pop()
        if (dp[a] == -2) {
            dp[a] = -1
            stack.push(a)
            stack.addAll(rev[a])
        } else {
            if (dp[a] == -1) {
                dp[a] = 0
                for (b in rev[a]) {
                    dp[a] = Math.max(dp[a], dp[b] + 1)
                }
            }
            answer = Math.max(answer, dp[a])
        }
    }
    println(answer)
}