// Slower C++ solution:
#include<iostream>

#include<iomanip>

#include<cmath>

#include<string>

#include<cctype>

#include<algorithm>

#include<set>

#include<map>

#include<stack>

#include<queue>

#include<cstring>

//#include<windows.h>

//#include<time.h>

#define pb push_back

#define ppb pop_back

#define fi first

#define se second

#define mer make_pair

#define mme memset

using namespace std;



const double pie1=3.1415926;//π1

const double pie2=3.14159265358979;//π2

const double pie3=3.14159265358979323846;//π3

const int vbi=999999999;

const int vli=-vbi;

const long long vbl=999999999999999999;

const long long vll=-vbl;



typedef long long ll;

typedef pair<int,int> pii;

typedef pair<ll,ll> pll;

typedef pair<pii,int> piii;

typedef pair<pii,pii> pi4;

typedef pair<pll,ll> plll;

typedef pair<int,pii> ipii;

typedef pair<ll,pll> lpll;

typedef pair<pll,pll> pl4;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef vector<pii> vpi;

typedef vector<pll> vpl;

typedef set<int> sti;

typedef set<ll> stl;

typedef set<pii> spi;

typedef set<pll> spl;

priority_queue<int> pqi;

priority_queue<ll> pql;

queue<int> qi;

queue<ll> ql;



/*void bin_v(){

	char bin[1000];

	gets(bin);

}*/



bool pss(int a){

	for(int i=2;i<=sqrt(a);i++)

		if(a%i==0)

			return false;

	return true;

}

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

int n,m;

vector<int> v[100010];

int d[100010];

int dp[100010];



int main(){

	//my name is Veex_WCY

	ios::sync_with_stdio(false);

	cin>>n>>m;

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

		int a,b;

		cin>>a>>b;

		v[a].pb(b);

		d[b]++;

	}

	stack<int> st;

	for(int i=1;i<=n;i++)

		if(d[i]==0)

			st.push(i);

	while(!st.empty()){

		int x=st.top();

		st.pop();

		for(int i=0;i<v[x].size();i++){

			int ne=v[x][i];

			if(dp[x]+1>dp[ne])

				dp[ne]=dp[x]+1;

			d[ne]--;

			if(d[ne]==0)

				st.push(ne);

		}

	}

	int maxn=0;

	for(int i=1;i<=n;i++)

		maxn=max(maxn,dp[i]);

	cout<<maxn;

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 2.5203916565127664x):
/*

██╗  ██╗ █████╗ ██████╗ ███████╗███████╗███╗   ███╗        ██╗  ██╗██╗  ██╗ █████╗ ██╗     ███████╗██████╗

██║ ██╔╝██╔══██╗██╔══██╗██╔════╝██╔════╝████╗ ████║        ██║ ██╔╝██║  ██║██╔══██╗██║     ██╔════╝██╔══██╗

█████╔╝ ███████║██████╔╝█████╗  █████╗  ██╔████╔██║        █████╔╝ ███████║███████║██║     █████╗  ██║  ██║

██╔═██╗ ██╔══██║██╔══██╗██╔══╝  ██╔══╝  ██║╚██╔╝██║        ██╔═██╗ ██╔══██║██╔══██║██║     ██╔══╝  ██║  ██║

██║  ██╗██║  ██║██║  ██║███████╗███████╗██║ ╚═╝ ██║███████╗██║  ██╗██║  ██║██║  ██║███████╗███████╗██████╔╝

╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝╚═════╝

Believe in yourself ,( try and try and then try ), You can do it

*/

#define _CRT_SECURE_NO_WARNINGS

#include<bits/stdc++.h>

#include<unordered_map>

#define endl "\n"

#define Ceil(x,y) ((x+y-1)/y)

#define clr(arr, x) memset(arr, x, sizeof arr)

#define all(v) v.begin(),v.end()

#define allr(s) s.rbegin(),s.rend()

#define rt(s) return cout<<s,0

#define watch(x) cout<<(#x)<<" = "<<x<<endl

#define sz(s)	(int)(s.size())

#define OO 0x3f3f3f3f3f3f3f3fLL

const int oo = 0x3f3f3f3f, mod = 1e9 + 7;

using namespace std;

typedef long long ll;

typedef long double ld;

typedef unsigned long long ull;

int dx[] { 1, -1, 0, 0, 1, 1, -1, -1 };

int dy[] { 0, 0, 1, -1, 1, -1, 1, -1 };

void K_K(){ 

	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

}

vector<vector<int>>gr;

int dp[100005];

int dfs(int node){

	if (!sz(gr[node]))

		return 0;

	int &ret = dp[node];

	if (~ret)

		return ret;

	for (auto child : gr[node]){

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

	}

	return ret;

}

int main(){

	K_K();

	int n, m;

	cin >> n >> m;

	gr.resize(n + 1);

	clr(dp, -1);

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

		int u, v;

		cin >> u >> v;

		gr[u].push_back(v);

	}

	int ans = 0;

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

		dfs(i);

		ans = max(ans, dp[i]);

	}

	cout << ans;

}