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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<bits/stdc++.h>
using namespace std;
#define  inf 2e18
#define  bg begin()
#define  en end()
#define  ll long long int
#define  pb push_back
#define  mp make_pair
#define  mod 1000000007
#define  vi vector<int>
#define  eb emplace_back
#define  lb(v,a) lower_bound(v.begin(),v.end(),a)
#define  ub(v,a) upper_bound(v.begin(),v.end(),a)
#define  bs binary_search
#define  vll vector<long long int>
#define  vpll vector<pair<long long int,long long int> >
#define  vpii vector<pair<int,int> >
#define  mpi map<int ,int>
#define  mpll map<long long int,long long int >
#define  max3(a,b,c) max(a,max(b,c))
#define  min3(a,b,c) min(a,min(b,c))
#define  w(t) ll t; cin>>t; while(t--)
#define  forn(i,n) for(int i=0;i<n;i++)
#define  forn1(i,n) for(int i=1;i<=n;i++)
#define  forv(it,v) for(auto it=v.begin();it!=v.end();it++)
#define  mem(a,val) memset(a,val,sizeof(a))
#define  Sort(vec) sort(vec.begin(),vec.end())
#define  RSort(vec) sort(vec.rbegin(),vec.rend())
#define  vin(v,n) for(int i=0;i<n;i++){cin>>x; v.pb(x);}
#define  deb1(x) cerr<<#x<<": "<<x<<" "<<endl
#define  deb2(x, y) cerr<<#x<<": "<<x<<" | "<<#y<<": "<<y<<endl
#define  deb3(x, y, z) cerr<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl
#define  deb4(a, b, c, d) cerr<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<endl
#define  FIFO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define  PI 3.141592653589793238462643383279502884L
void fifo() {
    FIFO;
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
    freopen("output.in", "w", stdout);
#endif
}
ll Ceil(ll a, ll b) {return a / b + (a % b != 0);}
ll fastModExp(ll a, ll b) { ll res = 1; while (b > 0) { if (b & 1)res = (res * a) % mod; a = (a * a) % mod; b = b >> 1; } return res;}
ll GC(ll a, ll b) { if (b == 0)return a; else  return GC(b, a % b);}
//Chrnlgy: Binary Search,Greedy,dp,dfs and similar

ll inv_gc(ll a, ll b) {return a / GC(a, b) * b;}


/*
ll xo,yo,z;
void exten_euclid(ll a,ll b)
{   ll temp;
    if(b==0)
    {
        z=a;
        xo=1;
        yo=0;
    }
    else
    {
        exten_euclid(b,a%b);
        temp=xo;
        xo=yo;
        yo=temp-(a/b)*yo;
    }
return;
}



//     O(sqrtn)

vector<ll> factorize(ll n) {
    vector<ll> res;
    for (ll i = 2; i * i <= n; ++i) {
        while (n % i == 0) {
            res.push_back(i);
            n /= i;
        }
    }
    if (n != 1) {
        res.push_back(n);
    }
    return res;
}

*************FACTORIZE IN 0(LOG(N)) PROVIDED N IS INTEGER**************

int minPrime[100000];

void modified_sieve(int n){
for (int i = 2; i * i <= n; ++i) {
    if (minPrime[i] == 0) {         //If i is prime
        for (int j = i * i; j <= n; j += i) {
            if (minPrime[j] == 0) {
                minPrime[j] = i;
            }
        }
    }
}
for (int i = 2; i <= n; ++i) {
    if (minPrime[i] == 0) {
        minPrime[i] = i;
    }
}
}

vector<int> factorize(int n) {
    vector<int> res;
    while (n != 1) {
        res.push_back(minPrime[n]);
        n /= minPrime[n];
    }
    return res;
}

*************************************************
void sieve(int N) {
        bool isPrime[N+1];
        for(int i = 0; i <= N;++i) {
            isPrime[i] = true;
        }
        isPrime[0] = false;
        isPrime[1] = false;
        for(int i = 2; i * i <= N; ++i) {
             if(isPrime[i] == true) {
                 for(int j = i * i; j <= N ;j += i)
                     isPrime[j] = false;
            }
        }
    }


ll binomialCoeff(ll n, ll k)
{
     ll res = 1;
    if(n<k)
    return 0;

    // Since C(n, k) = C(n, n-k)
    if ( k > n - k )
        k = n - k;

    // Calculate value of
    // [n * (n-1) *---* (n-k+1)] / [k * (k-1) *----* 1]
    for (ll i = 0; i < k; ++i)
    {
        res *= (n - i);
        res /= (i + 1);
    }

    return res;
}


bool dfs_cycle(int root){
vis[root]=1;
bool temp=false;
for(int i=0;i<G[root].size();i++)
{
int v=G[root][i];
if(vis[v]==0)
temp|=dfs_cycle(v);
else if(vis[v]==1)
return true;
}
vis[root]=2;
return temp;
}


bool is_cyclic(int n){
    vector<int> mark(2000,-1);
    queue<int> q;
    q.push(n);
    mark[n]=0;
    while(!q.empty()){
    int v=q.front();
    q.pop();
    for(int i=0;G[v].size();i++){
        int nbs=G[v][i];
        if(mark[nbs]==-1){
        q.push(nbs);
        mark[nbs]=0;
        }
        else if(mark[nbs]==0) return true;
    }
    mark[v]=1;
    }
    return false;
}



*/
vector<vector<int> > G;
vector<int> vis;
int d[100008];
void DFS_UTIL(ll u) {
    vis[u] = true;

    for (auto it = G[u].begin(); it != G[u].end(); it++) {
        if (vis[*it] == false)
        {   //d[u] = d[*it] + 1;
            DFS_UTIL(*it);

        }
        d[u] = max(d[u], d[*it] + 1);
        //count = 0;
    }
    //d[u] = ans;
}



map<int, int> par, rk;
void make_set(int n) // the rank and parent
{
    for (int i = 1; i <= n; i++) { par[i] = i; rk[i] = 1; }
}

int find( int x)   // with PATH COMPRESSION
{
    if (x == par[x]) return x;
    int p = find(par[x]);
    par[x] = p;
    return p;
}

int uni(int x, int y) // with UNION BY rank
{
    int p1 = find(x);
    int p2 = find(y);
    if (p1 == p2 ) return 0;
    if ( rk[p1] >= rk[p2] ) { par[p2] = p1; rk[p1] += rk[p2]; }
    else { par[p1] = p2; rk[p2] += rk[p1]; }
    return 1;
}
/*


void bfs(int o,int dp[],int n){
    queue<int> q;
    q.push(o);
    dp[o]=0;
    bool visited[n+1]={0};
    visited[o]=true;
    while(q.empty()==false){
        int a=q.front();
        q.pop();
        for (int u : G[a]) {
            if(visited[u]==false){
                visited[u]=true;
                q.push(u);

                dp[u]=dp[a]+1;
            }
        }
    }
}

struct comp{
    bool operator()(const pair<int,int>&a,const pair<int,int>&b) const {
        if(a.first>b.first) return true;
        if(a.first<b.first) return false;
        if(a.second<b.second) return true;
        return false;
    }
};



*/
mpi mpx, mpx2;
int main()
{
    //fifo();
    FIFO;
    int n, m, s, a, b;
    cin >> n >> m;
    G.resize(n + 1);
    vis.resize(n + 1);
    vis.assign(n + 1, false);
    mem(d, 0);
    forn1(i, m) {
        cin >> a >> b;
        G[a].pb(b);
    }
    for (int i = 1; i <= n; i++)
        DFS_UTIL(i);
    int mn = INT_MIN;
    forn1(i, n)
    {
        mn = max(mn, d[i]);
    }
    cout << mn;
    return 0;
}