// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

#define int long long 



const int INF = 1e9 + 5;  



void min_self ( int& a, int b  ) {

	a = min (a, b);

}



void max_self ( int& a, int b  ) {

	a = max (a, b);

}





std::vector< int > AdjList[100001];

int dp[100001];

std::vector<bool> vis;



auto dfs( int current ) -> int {

	

	if( dp[current] != -1 ) return dp[current];

	int ret = 0;

	for ( auto const& to : AdjList[current] ) {

		ret = max( ret, dfs(to) + 1 ); 

	}

	return dp[current] = ret;

}



auto solve ( int N ) -> int {

	

	int answer = -1;

	for ( int i = 1; i <= N; ++i ) {

		dp[i] = -1;

	}

	for ( int i = 1; i <= N; ++i ) {

		answer = max(answer , dfs(i));	

	}

	return answer;

}



signed

main () {



	int N, M;

	std::cin >> N >> M;

	int from, to;

	for ( int i = 0; i < M; ++i ) {

		std::cin >> from  >> to;

		AdjList[from].push_back(to);

	}

	std::cout << solve (N) << '\n';

	return 0;

}


// Optimized solution to the same problem (faster):
/////////////////////////////////////////////////////////////////////////////////

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'               `$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//  

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$'                   `$$$$$$$$$$$$$$$$$$$$$$$$$$$$//

//$$$'`$$$$$$$$$$$$$'`$$$$$$!                       !$$$$$$'`$$$$$$$$$$$$$'`$$$//

//$$$$  $$$$$$$$$$$  $$$$$$$                         $$$$$$$  $$$$$$$$$$$  $$$$//

//$$$$. `$' \' \$`  $$$$$$$!       $$        $$      !$$$$$$$  '$/ `/ `$' .$$$$//

//$$$$$. !\  i  i .$$$$$$$$       $$$$      $$$$      $$$$$$$$. i  i  /! .$$$$$//

//$$$$$$   `--`--.$$$$$$$$$        $$        $$       $$$$$$$$$.--'--'   $$$$$$//

//$$$$$$L        `$$$$$^^$$                           $$^^$$$$$'        J$$$$$$//

//$$$$$$$.   .'   ""~   $$$    $.                 .$  $$$   ~""   `.   .$$$$$$$//

//$$$$$$$$.  ;      .e$$$$$!    $$.             .$$  !$$$$$e,      ;  .$$$$$$$$//

//$$$$$$$$$   `.$$$$$$$$$$$$     $$$.         .$$$   $$$$$$$$$$$$.'   $$$$$$$$$//

//$$$$$$$$    .$$$$$$$$$$$$$!     $$`$$$$$$$$'$$    !$$$$$$$$$$$$$.    $$$$$$$$//

//$$$$$$$     $$$$$$$$$$$$$$$$.    $    $$    $   .$$$$$$$$$$$$$$$$     $$$$$$$//

//                                 $    $$    $								   //

//                                 $.   $$   .$								   //

//                                `$        $'								   //

//                                 `$$$$$$$$'								   //

/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////



#include <bits/stdc++.h>

using namespace std;



// Type-Define 

typedef long long ll;

typedef std::vector<int> vi;

typedef std::vector<std::string> vs;

typedef std::vector<char> vc;

typedef std::vector< vector<int> > vii;

typedef std::pair<int, int> pii;



// Hash-Define

#define int long long

#define MOD 1000000007

#define debugStart cerr << "\n[DEBUG START]\n"

#define debugStop cerr << "\n[DEBUG STOP]\n"

#define KHATAM cout << std::endl;

#define set_zero(x) memset(x, 0, sizeof(x));

#define ForPrint(x) std::for_each( begin(x), end(x), []( auto const& el ){ std::cout << el << " ";  } )



//Functions 

template<typename T> auto gcd ( T a, T b ) -> int  { return (b==0)?a:gcd(b,a%b); }



const int inf = 1e9 + 5;



std::vector< std::vector<int> > adj;

int N, M;



auto solve ( ) -> int {

    

    bool visited[N+1];

    int dist[N+1];

    memset( dist, 0, sizeof( dist ) );

    memset( visited, false, sizeof(visited) );

    std::function< int(int) > dfs = [&visited, &dist, &dfs]( int at ) -> int {

        

        if( visited[at] ) return dist[at];

        visited[at] = true;

        int max_el = 0;

        for ( auto& el : adj[at] ) {

            int value = dfs(el);

            max_el = max( max_el, value + 1 );

        }

        return dist[at] = max_el;

    };

    for ( int i = 1; i <= N; ++i ) {

        if( not visited[i] )

            dfs(i);

    }

    return *max_element(dist, dist + N + 1); 

}



signed

main() {



    ios::sync_with_stdio(0);

    cin.tie(0);

    int T = 1; 

    //cin >> T;

    for ( int testcase = 1; testcase <= T; ++testcase ) {

        

        std::cin >> N >> M;

        adj = std::vector< vector<int> > ( N + 1 );

        while ( M-- ) {

            int u, v;

            std::cin >> u >> v;

            adj[u].push_back(v);

        }    

        std::cout << solve();

        KHATAM;

    }

    return 0;

}


// Fastest known solution for this problem: