题目链接:https://www.luogu.org/problem/P3119;
/*
首先我们可以通过缩点将一个强连通分量里的所有点变成一个点,并且可以知道缩点以后的图是没有环的,
此时我们记缩点以后以一号点在第start个强连通分量里;
然后用spaf得出以start到其他点(缩点以后的点)的最长路dis1[],然后用反向的路在得到所有点到start
的最长路dis2[],最后我们可以遍历所以路的反向路得到答案;
ans=max(ans,dis1[b]+dis2[a]-sum[start]);
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
struct node
{
int v,ne;
} q[N];
struct note
{
int v,ne,w;
} edge1[N],edge2[N];//记录缩点以后的正反向路
int low[N],dfn[N],belong[N],sum[N],vis[N];
int f[N],f1[N],f2[N];
int dis1[N],dis2[N];
int top,cnt,e1,e2,m,n;
stack<int>sta;
void add(int a,int b)
{
q[e1].v=b;
q[e1].ne=f[a];
f[a]=e1++;
}
void add1(int a,int b,int c)
{
edge1[e1].v=b;
edge1[e1].ne=f1[a];
edge1[e1].w=c;
f1[a]=e1++;
}
void add2(int a,int b,int c)
{
edge2[e2].v=b;
edge2[e2].ne=f2[a];
edge2[e2].w=c;
f2[a]=e2++;
}
void tarjan(int now,int pre)///tarjan缩点
{
low[now]=dfn[now]=++top;
vis[now]=1;
sta.push(now);
for(int i=f[now]; i!=-1; i=q[i].ne)
{
int v=q[i].v;
if(!dfn[v])
{
tarjan(v,now);
low[now]=min(low[now],low[v]);
}
else if(vis[v])
low[now]=min(low[now],dfn[v]);
}
if(low[now]==dfn[now])
{
int v,se=0;
cnt++;
while(true)
{
se++;
v=sta.top();
sta.pop();
belong[v]=cnt;///每个点属于哪个强连通分量
vis[v]=0;
if(v==now)
break;
}
sum[cnt]=se;///每个强连通分量里点的个数
}
}
void spaf(int s,int dis[],int ff[],note edge[])
{
queue<int>que;
que.push(s);
memset(vis,0,sizeof(vis));
dis[s]=sum[s];
vis[s]=1;
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=0;
for(int i=ff[u]; i!=-1; i=edge[i].ne)
{
int v=edge[i].v,w=edge[i].w;
if(dis[v]<dis[u]+w)///spaf稍微改动一下求最长路
{
dis[v]=dis[u]+w;
if(vis[v]==0)
{
vis[v]=1;
que.push(v);
}
}
}
}
}
int main()
{
// freopen("E:\\in.txt","r",stdin);
scanf("%d %d",&n,&m);
int a,b;
memset(f,-1,sizeof(f));
memset(f1,-1,sizeof(f1));
memset(f2,-1,sizeof(f2));
for(int i=1; i<=m; i++)
{
scanf("%d %d",&a,&b);
add(a,b);
}
for(int i=1; i<=n; i++)
{
if(!dfn[i])
tarjan(i,-1);
}
int ans=sum[belong[1]];
e1=e2=0;
for(int i=1; i<=n; i++)
{
for(int j=f[i]; j!=-1; j=q[j].ne)
{
int v=q[j].v;
a=belong[i];b=belong[v];
if(a!=b)
{
add1(a,b,sum[b]);///添加正向边
add2(b,a,sum[a]);///添加反向边
}
}
}
spaf(belong[1],dis1,f1,edge1);
spaf(belong[1],dis2,f2,edge2);
for(int i=1; i<=n; i++)
{
for(int j=f[i]; j!=-1; j=q[j].ne)
{
int v=q[j].v;
a=belong[i];
b=belong[v];
if(a!=b)
{
if(dis1[b]!=0&&dis2[a]!=0)
ans=max(ans,dis1[b]+dis2[a]-sum[belong[1]]);
}
}
}
printf("%d\n",ans);
return 0;
}