stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



int dp[100005];



vector<int>adj[100005];



int dfs(int x){

    if (dp[x] != 0) return dp[x];

    int res = 0;

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

        res = max(dfs(adj[x][i]),res);

    }

    return dp[x] = 1+res;

}



int main(int argc, char const *argv[]) {

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    int n,m; cin >> n >> m;

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

        int x,y; cin >> x >> y;

        adj[x].push_back(y);

    }

    int res = 0;

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

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

    }

    cout << res-1 << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;



const int maxn=1e5+5;

struct edge{

	int to,next;

}e[maxn];



int head[maxn];

int cnt,ans;



void add(int x,int y)

{

	e[cnt].to=y;

	e[cnt].next=head[x];

	head[x]=cnt;

	cnt++;

}



int ru[maxn],chu[maxn],dp[maxn];

int dfs(int x)

{

	if(chu[x]==0) return 0;

	if(dp[x]) return dp[x];

	int ans=0;

	

	for(int i=head[x];~i;i=e[i].next)

	ans=max(dfs(e[i].to)+1,ans);

	

	return dp[x]=ans;

}



int main()

{

	int n,m,x,y;

	memset(head,-1,sizeof(head));

	cin>>n>>m;

	while(m--)

	{

		cin>>x>>y;

		add(x,y);

		ru[y]++;

		chu[x]++;

	}

	

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

	{

		if(!ru[i])

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

	}

	cout<<ans<<endl;

	

	return 0;

 } 

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std ;

#define ll long long



inline int D(){

    int t ;

    scanf( "%d" , &t ) ;

    return t ;

}

inline ll LLD(){

    ll t ;

    scanf( "%lld" , &t ) ;

    return t ;

}

//const int INF = 0x3f3f3f3f;

//const int mod=1e9+7;

//###################################################################

const int N=100009;

int n,m;

vector<vector<int>>g(N);



int mem[N];

int solve(int num){

    if(mem[num]!=-1)return mem[num];

    if(g[num].size()) {

        int ret=0;

        for (auto i:g[num]) {

            ret =max(ret,solve(i));

        }

        return mem[num]=1+ret;

    }

    return mem[num]=0;



}



int main(){

    n=D(),m=D();

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

        int u=D(),v=D();

        g[u].push_back(v);

    }

    int mx=0;

    memset(mem,-1,sizeof(mem));

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

        mx=max(mx,solve(i));

    }

    printf("%d",mx);

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;



const int maxn=1e5+5;

struct edge{

	int to,next;

}e[maxn];



int head[maxn];

int cnt,ans;



void add(int x,int y)

{

	e[cnt].to=y;

	e[cnt].next=head[x];

	head[x]=cnt;

	cnt++;

}



int ru[maxn],chu[maxn],dp[maxn];

int dfs(int x)

{

	if(chu[x]==0) return 0;

	if(dp[x]) return dp[x];

	int ans=0;

	

	for(int i=head[x];~i;i=e[i].next)

	ans=max(dfs(e[i].to)+1,ans);

	

	return dp[x]=ans;

}



int main()

{

	int n,m,x,y;

	memset(head,-1,sizeof(head));

	cin>>n>>m;

	while(m--)

	{

		cin>>x>>y;

		add(x,y);

		ru[y]++;

		chu[x]++;

	}

	

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

	{

		if(!ru[i])

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

	}

	cout<<ans<<endl;

	

	return 0;

 } 

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



vector <int> dp[100010], ed[100010];



int solve(int i, int j){

	

	if(j == (int)ed[i].size()) return 0;

	

	if(dp[i][j] == -1) dp[i][j] = max(solve(ed[i][j], 0) + 1, solve(i, j + 1));

	

	return dp[i][j];

}

	



int main(){

	

	int n, m, ans = 0;

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

	

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

		int a, b;

		scanf(" %d %d", &a, &b);

		

		ed[a].push_back(b);

		dp[a].push_back(-1);

	}

	

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

		for(int j = 0; j < (int)ed[i].size(); j++){

			if(dp[i][j] == -1) solve(i, j);

			

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

		}

	}

	

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

	

	return 0;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;



const int maxn=1e5+5;

struct edge{

	int to,next;

}e[maxn];



int head[maxn];

int cnt,ans;



void add(int x,int y)

{

	e[cnt].to=y;

	e[cnt].next=head[x];

	head[x]=cnt;

	cnt++;

}



int ru[maxn],chu[maxn],dp[maxn];

int dfs(int x)

{

	if(chu[x]==0) return 0;

	if(dp[x]) return dp[x];

	int ans=0;

	

	for(int i=head[x];~i;i=e[i].next)

	ans=max(dfs(e[i].to)+1,ans);

	

	return dp[x]=ans;

}



int main()

{

	int n,m,x,y;

	memset(head,-1,sizeof(head));

	cin>>n>>m;

	while(m--)

	{

		cin>>x>>y;

		add(x,y);

		ru[y]++;

		chu[x]++;

	}

	

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

	{

		if(!ru[i])

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

	}

	cout<<ans<<endl;

	

	return 0;

 } 

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;





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

typedef  long long ull;

typedef long long ll;





ll const oo=1e9 ;

int const SZ= (int)1e5+3;

const ll mod=(ll)1e9+7;





vector<int> adj[SZ];

//int arr[100];

int dp[SZ];

int n,m;



int solve(int i){



    int &ret=dp[i];

    if(~ret) return ret;

    int mx=0;

    for(int x: adj[i]){

        mx=max(mx,solve(x));

    }

    return ret=1+mx;

    

}

int main()

{

    

    cin>>n>>m;

    int u,v;

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

        cin>>u>>v; 

        adj[u].push_back(v);

    }

    clr(dp,-1);

    int mx=0;

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

        mx=max(mx,solve(i));

    }

    

    cout<<mx-1<<endl;

    

    return 0;

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define REP(x,y,z) for(int x=y;x<=z;x++)

#define MSET(x,y) memset(x,y,sizeof(x))

#define M 100005

using namespace std;

int n,m,dp[M];

bool vis[M];

vector<int> e[M];

int dfs(int cur) {

    if (vis[cur]) {

        return dp[cur];

    }



    int &res = dp[cur];

    for (int i:e[cur]) res = max(res, 1+dfs(i));

    vis[cur] = true;

    return res;

}

int main()

{

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

    REP(i,1,m) {

        int x,y;

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

        e[x].push_back(y);

    }



    int ans = 0;

    REP(i,1,n) ans = max(ans, dfs(i));

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

    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <cmath>

#include <cstdio>

#include <vector>

#include <iostream>

#include <algorithm>

#define ll long long

#define pb push_back

using namespace std;

vector<ll>adj[100005];

vector<ll>indegree(100005,0),dp(100005,-1);

ll dfs(ll node)

{

    if(adj[node].size()==0)

    return dp[node]=1;

    if(dp[node]!=-1)

    return dp[node];

    ll x=0;

    for(auto u:adj[node])

    {

        if(dp[u]==-1)

        x=max(x,dfs(u));

        else

        x=max(x,dp[u]);

    }

    return dp[node]=x+1;

}

int main() {

    ll n,m,i,x,y;cin>>n>>m;

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

    {

        cin>>x>>y;

        adj[x].pb(y);

        indegree[y]++;

    }

    ll  ans=0;

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

    {

        if(indegree[i]==0)

        {

            dfs(i);

        }

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

    }

    cout<<ans-1;

    return 0;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define ll long long int

#define db long double

#define mp make_pair

#define F first

#define S second

#define pb push_back

#define rep(i,a,b)  for(ll i=a;i<=b;i++)

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

#define Nmax 1000005

#define INF 1000000000

#define MOD 1000000007

#define MAXN 1000005

 

using namespace std;



vector<ll> g[100001];

ll dp[100001],vis[100001];



void dfs(ll node,ll par)

{

	vis[node]=1;

	for(auto x:g[node])

	{

		if(x!=par && !vis[x])

			dfs(x,node);

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

	}

}



int main()

{

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    int tests=1,t=1;

    // cin>>tests;

    while(tests--)

    {	

    	ll i,j,n,m;

    	cin>>n>>m;

    	rep(i,1,m)

    	{

    		ll u,v;

    		cin>>u>>v;

    		g[u].pb(v);

    	}



    	rep(i,1,n)

    	{

    		if(!vis[i])

    			dfs(i,0);

    	}

    	ll ans=0;

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

    	cout<<ans;





    }

    	return 0;

    

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<iostream>

#include<sstream>

#include<fstream>

#include<string>

#include<vector>

#include<deque>

#include<queue>

#include<stack>

#include<set>

#include<map>

#include<algorithm>

#include<functional>

#include<utility>

#include<bitset>

#include<cmath>

#include<cstdlib>

#include<ctime>

#include<cstdio>

using namespace std;

int n,m,dp[202020],in[202020];

vector<int>v[202020];

queue<int>tpx;

int main()

{

	cin>>n>>m;

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

	{

		int a,b;

		cin>>a>>b;

		a--;

		b--;

		v[a].push_back(b);

		in[b]++;

	}

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

	{

		if(!in[i])

		{

			tpx.push(i);

		}

	}

	while(tpx.size())

	{

        int i=tpx.front();

        tpx.pop();

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

		{

            dp[v[i][j]]=max(dp[i]+1,dp[v[i][j]]);

            in[v[i][j]]--;

            if(!in[v[i][j]])

			{

				tpx.push(v[i][j]);

			}

        }

    }

	int ans=0;

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

	{

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

	}

	cout<<ans<<endl;

	return 0;

}

// Optimized solution to the same problem (faster):
#include<iostream>

#include<sstream>

#include<fstream>

#include<string>

#include<vector>

#include<deque>

#include<queue>

#include<stack>

#include<set>

#include<map>

#include<algorithm>

#include<functional>

#include<utility>

#include<bitset>

#include<cmath>

#include<cstdlib>

#include<ctime>

#include<cstdio>

using namespace std;

int n,m,id[101010],l[101010],bf[101010];

vector<int>g[101010];

int main()

{

	cin>>n>>m;

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

	{

		int x,y;

		cin>>x>>y;

		x--;

		y--;

		g[x].push_back(y);

		id[y]++;

	}

	fill(bf,bf+n,-1);

	stack<int>s;

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

	{

		if(id[i]==0)

		{

			s.push(i);

		}

	}

	while(s.size())

	{

		int p=s.top();

		s.pop();

		for(int i=0;i<g[p].size();i++)

		{

			int to=g[p][i];

			if(l[p]+1>l[to])

			{

				l[to]=l[p]+1;

			}

			id[to]--;

			if(!id[to])

			{

				s.push(to);

			}

		}

	}

	cout<<*max_element(l,l+n)<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;



const int MaxN = 100000 + 5, MaxM = 100000 + 5;



int N, M; int cnte;

int Head[MaxN], To[MaxM], Next[MaxM];

int ind[MaxN], dp[MaxN];

queue <int> que;



inline void add_edge(int from, int to) {

  cnte++; To[cnte] = to;

  Next[cnte] = Head[from]; Head[from] = cnte;

}



void init() {

  scanf("%d %d", &N, &M);

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

    int u, v;

    scanf("%d %d", &u, &v);

    add_edge(u, v);

    ind[v]++;

  }

}



void solve() {

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

    if (ind[i] == 0) {

      que.push(i);

      dp[i] = 0;

    }



  while (!que.empty()) {

    int u = que.front(); que.pop();

    for (int i = Head[u]; i; i = Next[i]) {

      int v = To[i];

      dp[v] = max(dp[v], dp[u] + 1);

      ind[v]--;

      if (ind[v] == 0) que.push(v);

    }

  }



  int ans = 0;

  for (int i = 1; i <= N; ++i) ans = max(ans, dp[i]);

  cout << ans << endl;

}



int main() {

  init();

  solve();

  return 0;

}

// Optimized solution to the same problem (faster):
#include <cstdio>



const int MaxN = 100000 + 5, MaxM = 100000 + 5;



struct Graph {

  int cnte;

  int Head[MaxN], To[MaxM], Next[MaxM];



  inline void addEdge(int from, int to) {

    cnte++; To[cnte] = to;

    Next[cnte] = Head[from]; Head[from] = cnte;

  }

};



int N, M;

int Ind[MaxN];

int Dp[MaxN];

Graph G;



inline int max(int x, int y) { return x > y ? x : y; }



void init() {

  scanf("%d %d", &N, &M);

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

    int u, v;

    scanf("%d %d", &u, &v);

    Ind[v]++;

    G.addEdge(u, v);

  }

}



void solve() {

  static int que[MaxN];

  int head = 1, tail = 0;

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

    if (Ind[i] == 0) que[++tail] = i;

  while (head <= tail) {

    int u = que[head++];

    for (int i = G.Head[u]; i; i = G.Next[i]) {

      int v = G.To[i];

      Dp[v] = max(Dp[v], Dp[u] + 1);

      Ind[v]--;

      if (Ind[v] == 0) que[++tail] = v;

    }

  }

  int ans = 0;

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

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

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

}



int main() {

  init();

  solve();

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h> 

using namespace std;

#define int long long int

#define float double

#define pb push_back

#define FF first

#define SS second

#define N 201000

#define MOD 1000000007

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

#define rep(i,l,r) for(int i=l;i<=r;i++)

#define pii pair<int,int>

#define mp make_pair

#define INF 1000000000000000000

#define speed ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)



vector<int> adj[N];

int vis[N]={};

int dp[N]={};

int dfs(int a)

{

    vis[a]=1;

    fn(i,adj[a].size()) 

    {

        if(!vis[adj[a][i]]) dfs(adj[a][i]);

        dp[a]=max(dp[a],1+dp[adj[a][i]]);

    }

    return dp[a];

}

signed main() 

{

    speed;

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

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



    int n,m;

    cin>>n>>m;



    fn(i,m)

    {

        int a,b;

        cin>>a>>b;

        adj[a].pb(b);

    }

    int ans=0;

    rep(i,1,n) if(!vis[i]) ans=max(ans,dfs(i));

    cout<<ans;

}   

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h> 

using namespace std;

#define int long long int

#define float double

#define pb push_back

#define FF first

#define SS second

#define N 100005

#define MOD 1000000007

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

#define rep(i,l,r) for(int i=l;i<=r;i++)

#define pii pair<int,int>

#define mp make_pair

#define INF 9223372036854775807

#define speed ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)



int n,m;

vector<int> adj[N];

int dp[N];

int ans=0;



int dfs(int node)

{

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

    dp[node]=0;

    for(auto child:adj[node]) dp[node]=max(dfs(child)+1,dp[node]);

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

    return dp[node];

}





signed main() 

{

    speed;

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

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



    cin>>n>>m;

    memset(dp,-1,sizeof(dp));

    fn(i,m)

    {

        int u,v;

        cin>>u>>v;

        adj[u].pb(v);

    }



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

    {

        if(dp[i]==-1) dfs(i);

    }

    cout<<ans<<endl;

}   

// Fastest known solution for this problem:
// Original C++ solution (slower):
/**

 *   author: Shubham Srivastava

 *   created: 04 February 2019  18:24:54

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

vector <long long> nodes[100005];

bool visited[100005] = {0};

vector <long long> dp(100005);

vector <long long> v;

ll maxi = -1;

ll dfs(ll s)

{

	if(dp[s])

		return dp[s];

	dp[s] = 0;

	for(auto i : nodes[s])

	{

		dp[i] = dfs(i);

		dp[s] = max(dp[s],dp[i]+1);

	}

	return dp[s];

}



int main(){

    ios_base::sync_with_stdio(false); 

    cin.tie(NULL);

    long long n,m;

    cin>>n>>m;

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

    {

    	int a,b;

    	cin>>a>>b;

    	nodes[a].push_back(b);

    }

    ll ans = -1;

	for(ll p = 1; p <= n; p++)

		ans = max(ans, dfs(p));

    cout<<ans;

return 0;

}

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

 *   author: Shubham Srivastava

 *   created: 27 January 2020  12:16:37

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

#define MOD 1000000007

#define INF 0x7fffffff

#define sorti(v) sort(v.begin(),v.end())

#define sortd(v) sort(v.rbegin(),v.rend())

typedef pair<ll, ll> pll;

typedef pair<int, int> pii;

typedef vector<int> vi;

typedef vector<pii> vii;

ll parent[2000005];

vector <ll> arr;

vector <int> node[100005], vis(100005,false);

void dfs(ll n){

	vis[n] = 1;

	for(auto i : node[n]){

		if(!vis[i])

			dfs(i);

	}

	arr.push_back(n);

}



int main(){

    ios_base::sync_with_stdio(false); 

    cin.tie(NULL);

    ll n,m;cin>>n>>m;

    vector <int> dp(n+1,0);

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

    	ll a,b;cin>>a>>b;

    	node[a].push_back(b);

    }

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

    	if(!vis[i])

    		dfs(i);

    reverse(arr.begin(),arr.end());

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

    	for(auto j : node[arr[i]]){

    		dp[j] = max(dp[j],dp[arr[i]]+1);

    	}

    }

    int ans = 0;

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

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

    cout<<ans;

return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



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

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

#define _GLIBCXX_DEBUG

#define llint long long

const double pi=3.141592653589793;



vector<int> dp(100010,0);

vector<int> p(100010,0);

vector<vector<int>> st(100010,vector<int>(0));

vector<vector<int>> ts(100010,vector<int>(0));



//sを始点とする最長パスをdpで求める



int ddpp(int s){

    if (p[s]==1){

        return dp[s];

    }

    else{

        p[s]=1;

        int m1=0;

        if (st[s].size()==0){

            dp[s]=0;

            return 0;

        }

        for (int x:st[s]){

            m1=max(m1,ddpp(x));

        }

        dp[s]=1+m1;

        return dp[s];

    }

}

int main() {

    int n,m;

    cin>>n>>m;

    rep(i,m){

        int x,y;

        cin>>x>>y;

        st[x].push_back(y);

        ts[y].push_back(x);

    }

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

        if (ts[i].size()==0){

            ddpp(i);

        }

    }

    int mmm=0;

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

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

    }

    cout<<mmm<<endl;



    



    return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



using namespace std;



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

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

#define _GLIBCXX_DEBUG



using ll = long long;

using vi = vector<int>;

using vll = vector<ll>;

using vd = vector<double>;

using vvi = vector<vi>;

using vvll = vector<vll>;

using vvd = vector<vd>;

using vvvi = vector<vvi>;

using vvvll = vector<vvll>;

using vvvd = vector<vvd>;



const double pi=3.141592653589793;



int n,m;

int dp[100010];

int flag[100010];

vvi to(100010,vi(0));



int ddpp(int x){

    if(flag[x]){

        return dp[x];

    }

    else{

        flag[x]=1;

        auto xto=to[x];

        int ans1=0;

        if (xto.size()==0){

            dp[x]=ans1;

            return ans1;

        }

        else{

            for (int y:xto){

                ans1=max(ans1,ddpp(y)+1);

            }

            dp[x]=ans1;

            return dp[x];

        }

        

    }

}



int main() {

    cin>>n>>m;

    rep(i,m){

        int x,y;

        cin>>x>>y;

        to[x].push_back(y);

    }

    int ans=0;

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

        ans=max(ddpp(i),ans);

        //cout<<dp[i]<<endl;

    }

    cout<<ans<<endl;

    



    return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
// G - Longest Path

#include <bits/stdc++.h>

using namespace std;

using vi = vector<int>;

using vvi = vector<vi>;



int N,M;



#define VMAX 100000



vvi V(VMAX+1);//vertex

vi D(VMAX+1);//depth



int dfs(int p){//parent 後置でD設定

	if(D[p]>0) return D[p];

	if(V[p].size()<=0) return 0;

	for(auto c:V[p]){

		D[p] = max(D[p], dfs(c)+1);

	}

	return D[p];

}



int main(){

	cin>>N>>M;



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

		int x,y; cin>>x>>y;

		V[x].push_back(y);

	}



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

		if(D[p]<=0) D[0] = max(D[0], dfs(p));

	}

	cout<< D[0] <<endl;

}

// Optimized solution to the same problem (faster):
// G - Longest Path

#include <bits/stdc++.h>

using namespace std;

using vi = vector<int>;

using vvi = vector<vi>;



int dfs(vvi &V, vi &D, int p){

	if(D[p]>0 || V[p].size()<=0) return D[p];

	for(int c:V[p]) D[p] = max(D[p], dfs(V,D,c)+1);

	return D[p];

}



int in(){int x;cin>>x;return x;}



int main(){

	int N,M; cin>>N>>M;



	vvi V(N+1);

	while(M--) V[in()].push_back(in());



	vi D(N+1);

	for(int p=1; p<=N; p++) if(D[p]<=0) D[0] = max(D[0], dfs(V,D,p));



	cout<< D[0] <<endl;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



vector<int> v[100001];

bool visited[100001];

int dp[100001];



void dfs(int idx)

{

    int num=0;

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

    {

        if(!visited[v[idx][i]])

        {

            visited[v[idx][i]]=1;

            dfs(v[idx][i]);

        }

        num=max(num,dp[v[idx][i]]+1);

    }

    dp[idx]=num;

}



int main()

{

    int n,m;

    cin >> n >> m;

    int x,y;

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

    {

        cin >> x >> y;

        v[x].push_back(y);

    }

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

    int res=0;

    for(int i=1;i<=n;i++) res=max(res,dp[i]);

    cout << res << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



using namespace std;

typedef long long ll;



int main()

{

    ios::sync_with_stdio(0);

    cin.tie(0);

    int n,m;

    cin >> n >> m;

    vector<int> vr[n+1];

    vector<int> out(n+1,0);

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

    {

        int a,b;

        cin >> a >> b;

        vr[b].push_back(a);

        out[a]++;

    }

    queue<int> q;

    for(int i=1;i<=n;i++) if(out[i]==0) q.push(i);

    vector<int> dp(n+1,0);

    while(!q.empty())

    {

        int a=q.front();

        q.pop();

        for(int to:vr[a])

        {

            dp[to]=max(dp[to],dp[a]+1);

            out[to]--;

            if(out[to]==0) q.push(to);

        }

    }

    int res=0;

    for(int i=1;i<=n;i++) res=max(res,dp[i]);

    cout << res << "\n";

    return 0;

}


// Fastest known solution for this problem: