#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=1000010;
int dfn[N],k=0,low[N],n,m,head[N],color[N],color_time,sta[N],top=0,tim=0,f[N],ans=0,rd[N],x[N],y[N];
bool vis[N];
struct node
{
int to,nxt,from;
}edge[N];
void add(int u,int v)
{
edge[++k].to=v;
edge[k].from=u;
edge[k].nxt=head[u];
head[u]=k;
}
int read()
{
int x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
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].nxt,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]++;//求染色后点集权值和
vis[sta[top]]=false;
top--;
}
}
}
int dfs(int x)
{
int ans1=f[x];
int ans2=0;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
ans2=max(ans2,dfs(v));
}
return ans1+ans2;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
u=read(),v=read();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]]);
rd[color[y[i]]]++;
}
}
for(int i=1;i<=color_time;i++)
{
if(!rd[i])
{
ans=max(ans,dfs(i));
}
}
cout<<ans<<endl;
}