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 JavaScript (node.js v5.12) (judge verdict: Time Limit Exceeded)

var output;
var input = require("fs").readFileSync("/dev/stdin", "utf8").trim().split("\n");
var obj = {
  "list" : input,
  "index" : 0,
  "max" : input.length,
  "next" : function(){
    if(!this.hasNext()){throw "NoSuchElementException:次に要素は無いよ";}
    var returnObj = this.list[this.index];
    this.index++;
    return returnObj;
  },
  "hasNext" : function(){return (this.index < this.max);}
}
Main();
function next(){return obj.next();}
function hasNext(){return obj.hasNext();}
function myout(t){console.log(t);}//standard output
function myerr(t){console.error(t);}//standard error
//[no]要素の扱い。数値型
//不明値、異常時:引数そのまま返す
//1:数値へ変換 2:半角SPで分割 4:半角SPで分割し、数値配列へ
//6:1文字に分割 7:1文字に分割し、数値配列へ
//8:半角SPで結合 9:改行で結合 0:文字なしで結合
function myconv(i,no){try{switch(no){case 1:return parseInt(i);case 2:return i.split(" ");case 4:return i.split(" ").map((a)=>Number(a));case 6:return i.split("");case 7:return i.split("").map((a)=>Number(a));case 8:return i.join(" ");case 9:return i.join("\n");case 0:return i.join("");default:return i;}}catch(e){return i;}}
function Main() {
  var one = myconv(next(),4);
  var N = one[0];
  var M = one[1];
  var list = new Array(N);
  for(var i = 0; i < N; i++){
    var obj = {};
    obj["child"] = [];
    obj["count"] = 0;
    obj["visit"] = false;
    list[i] = obj;
  }
  for(var i = 0; i < M; i++){
    var tmp = myconv(next(),4);
    list[tmp[0]-1]["child"].push(tmp[1]-1);
  }
  var max = 0;
  for(var j = 0; j < N; j++){
    if(list[j]["visit"]){continue;}
  var queue = [];
  queue.push(list[j]);
  while(queue.length > 0){
     var tmp = queue.shift();
     tmp["visit"] = true;
     for(var i = 0; i < tmp["child"].length; i++){
        list[tmp["child"][i]]["count"] = Math.max(tmp["count"] + 1,list[tmp["child"][i]]["count"]);
       max = Math.max(max, list[tmp["child"][i]]["count"]);
       queue.push(list[tmp["child"][i]]);
     }
  }
  }
  
  myout(max);
}