// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

#define ALL(x) (x).begin(),(x).end()

#define uniq(x) (x).erase(unique(ALL(x)),(x).end())

#define SORT(x) sort(ALL(x))

#define REV(x) reverse(ALL(x))

#define foreach(it,x) for(__typeof((x).begin()) it=(x).begin();it!=(x).end();it++)

#define debug(x) cerr<<#x<<"="<<(x)<<endl

#define gett() cerr<<"Time:"<<clock()<<"ms."<<endl

#define ri(x) scanf("%d",&x)

#define rl(x) scanf("%lld",&x)

#define rlcfpoj(x) scanf("%I64d",&x)

#define pi(x) printf("%d",x)

#define pl(x) printf("%lld",x)

#define plcfpoj(x) printf("%I64d",x)

#define lfd() printf("\n")

#define sp() printf(" ")

#define inrep(x) int x;scanf("%d",&x);while(x--)

#define testbit(mask,i) (((mask)>>(i))&1)

#define setbit(mask,i) ((mask)|(1<<i))

#define delbit(mask,i) ((mask)^(1<<i))

int n,m,u,v;

vector<int> ga[100100];

int deg[100100];

int dp[100100];

int main(){

	//freopen("input.txt","r",stdin);

	//freopen("output.txt","w",stdout);

	ios::sync_with_stdio(false);

	cin.tie(NULL);

	cout.tie(NULL);

	cin>>n>>m;

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

		cin>>u>>v;

		ga[u].push_back(v);

		deg[v]++;

	}

	stack<int> s;

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

		if(deg[i]==0){

			s.push(i);

		} 

	}

	while(s.size()){

		int x=s.top();

		s.pop();

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

			int y=ga[x][i];

			deg[y]--;

			dp[y]=max(dp[y],dp[x]+1);

			if(deg[y]==0){

				s.push(y);

			}

		} 

	}

	cout<<*max_element(dp+1,dp+n+1);

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.573725913248635x):
#include <bits/stdc++.h>

#define eps 1e-3

#define pi acos(-1.0)

#define inf 0x3f

#define INF 0x3f3f3f3f

#define pb push_back

#define debug1 cout<<"&&";

#define debug2 cout<<"**";

#define ms(a, x) memset(a, x, sizeof(a))

#define for0(i, n) for(int i = 0; i < n; ++i)

#define for1(i, n) for(int i = 1; i <= n; ++i)

using namespace std;

typedef double db;

typedef long long ll;

typedef unsigned long long ull;

typedef pair<int, int> pii;

typedef pair<long long, int> pli;

typedef pair<long long, long long> pll;

const int mod = 1e9 + 7;

const int N = 1e5+10;

const int M = 1e6+10;

inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }

inline ll Pow(ll a, ll b) { ll ans = 1; for( ; b; b >>= 1) { if(b&1) ans = ans * a % mod; a = a * a % mod;} return ans;}

inline ll Mul ( ll a, ll b)  { ll lf = a * ( b >> 25ll ) % mod * ( 1LL << 25 ) % mod; ll rg = a * ( b & ( ( 1ll << 25 ) - 1 ) ) % mod; return ( lf + rg ) % mod;}

inline ll C(ll y, ll x) { ll ans = 1; if(y < 0 || x < 0 || y < x) return 0; y %= mod; if(!y || !x) return 1; for0(i, x) ans = ans * (y-i) % mod; for1(i, x) ans = ans * Pow(i, mod-2) % mod; return ans; }

//==================================================================================================================================================================//



int n, m, tot, head[N], nex[N], ver[N];

int dp[N], deg[N], ans;

queue<int> q;



void add(int x, int y) {

   ver[++tot] = y, nex[tot] = head[x], head[x] = tot;

}



int main() {

   scanf("%d %d", &n, &m);

   for1(i, m) {

      int x, y;

      scanf("%d %d", &x, &y);

      add(x, y);

      deg[y]++;

   }

   for1(i, n) if(!deg[i]) q.push(i);

   while(!q.empty()) {

      int x = q.front(); q.pop();

      for(int i = head[x]; i; i = nex[i]) {

         int y = ver[i]; deg[y]--;

         dp[y] = max(dp[y], dp[x] + 1);

         if(!deg[y]) q.push(y);

      }

   }

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

   printf("%d\n", ans);

   return 0;

}