#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=100000;
int dfn[N],k=0,low[N],n,m,head[N],color[N],color_time,sta[N],top=0,tim=0,value[N],f[N],ans=0,rd[N],dis[N],x[N],y[N];
bool vis[N];
struct node
{
int to,next,from;
}edge[N];
void add(int u,int v)
{
edge[++k].to=v;
edge[k].from=u;
edge[k].next=head[u];
head[u]=k;
}
void tarjan(int s)//缩点
{
dfn[s]=low[s]=++tim;
sta[++top]=s;
vis[s]=true;
for(int i=head[s],v=edge[i].to;i;i=edge[i].next,v=edge[i].to)
{
if(!dfn[v])tarjan(v),low[s]=min(low[s],low[v]);
else if(vis[v])low[s]=min(low[s],dfn[v]);
}
if(low[s]==dfn[s])
{
++color_time;
vis[s]=false;
while(sta[top+1]!=s)
{
color[sta[top]]=color_time;//染色
f[color_time]+=value[sta[top]];//求染色后点集权值和
ans=max(ans,f[color_time]);
vis[sta[top]]=false;
top--;
}
}
}
void bfs(int x)//spfa最大路
{
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[x]=f[x];
queue<int>q;
vis[x]=true;
q.push(x);
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=false;
for(int i=head[u],v=edge[i].to;i;i=edge[i].next,v=edge[i].to)
{
if(dis[v]<dis[u]+f[v])
{
dis[v]=dis[u]+f[v];
if(!vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
}
for(int i=1;i<=color_time;i++)ans=max(dis[i],ans);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)value[i]=1;
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);x[i]=u,y[i]=v;
add(u,v);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
memset(head,0,sizeof(head));
memset(edge,0,sizeof(edge));
k=0;
for(int i=1;i<=m;i++)
{
if(color[x[i]]!=color[y[i]])
{
add(color[x[i]],color[y[i]]);//重新建边
}
}
for(int i=1;i<=color_time;i++)
{
bfs(i);
}
printf("%d",ans);
}