这道题显然要先 Tarjan 缩点预处理;
这里就不多说了;
之后的点都是缩点之后点集;
我们考虑两种点:
<1> 以 1 为起点可以直接到达的; 我们这里叫它一类点;
<2> 以该点为起点,可以直接到达 1 的; 我们这里叫它二类点;
所以我们先用 spfa 处理出来从 1 到这两种点的点权值;
统计 ans 用;
然后枚举每一个一类点;
由于我们只能走一次反边;
所以我们所要的反边一定与一类点和二类点相连;
因为这样才能确保从 1 出发,再回到 1 ;
所以我们可以确定一类点和二类点相连的边一定满足;
那么我们枚举这些边;
然后统计所连两点的点权和;
更新 ans ;
但是由于在一开始 spfa 处理时;
1 这个点的点权计算了两遍;
所以最后要减掉;
#include "iostream"
#include "stdio.h"
#include "algorithm"
#include "vector"
#include "map"
#include "queue"
#define II int
#define R register
#define I 123546
using namespace std;
struct node {
II to,up;
} aa[I], aa_1[I];
II head[I], DFN[I], LOW[I], is[I], stack[I], vis[I], belong[I], nu[I];
II inq[I], in_just[I], dis_back[I], in_back[I], dis_just[I], head_1[I], dis[I];
II _tot,n,m,_top,_num,bit,ans,_tot_1;
vector <II> just[I], back[I];
queue <II> Q;
void add(R II x,R II y)
{
aa[++_tot].to=y;
aa[_tot].up=head[x];
head[x]=_tot;
}
void add_1(R II x,R II y)
{
aa_1[++_tot_1].to=y;
aa_1[_tot_1].up=head_1[x];
head_1[x]=_tot_1;
}
void Tarjan(R II x)
{
DFN[x]=LOW[x]=++_num;
stack[++_top]=x; vis[x]=1;
for(R II i=head[x];i;i=aa[i].up)
{
R II go=aa[i].to;
if(!DFN[go]) {
Tarjan(go);
LOW[x]=min(LOW[x],LOW[go]);
} else if(vis[go]) LOW[x]=min(LOW[x],DFN[go]);
}
if(LOW[x]==DFN[x]) {
bit++;
do {
R II o=stack[_top--];
vis[o]=0;
belong[o]=bit;
nu[bit]++;
} while (stack[_top+1]!=x) ;
}
}
void dfs_just(R II x)
{
in_just[x]=1;
for(R II i=0;i<just[x].size();i++)
{
R II go=just[x][i];
if(!in_just[go]) {
dfs_just(go);
}
}
}
void dfs_back(R II x)
{
in_back[x]=1;
for(R II i=0;i<back[x].size();i++)
{
R II go=back[x][i];
if(!in_back[go]) {
dfs_back(go);
}
}
}
void spfa_just()
{
for(R II i=1;i<=bit;i++) dis_just[i]=-1e9;
Q.push(belong[1]); inq[belong[1]]=1;
dis_just[belong[1]]=nu[belong[1]];
while (!Q.empty()) {
R II x=Q.front(); Q.pop(); inq[x]=0;
for(R II i=0;i<just[x].size();i++)
{
R II go=just[x][i];
if(dis_just[go]<dis_just[x]+nu[go]) {
dis_just[go]=dis_just[x]+nu[go];
if(!inq[go]) {
Q.push(go);
inq[go]=1;
}
}
}
}
}
void spfa_back()
{
for(R II i=1;i<=bit;i++) dis_back[i]=-1e9;
Q.push(belong[1]); inq[belong[1]]=1;
dis_back[belong[1]]=nu[belong[1]];
while (!Q.empty()) {
R II x=Q.front(); Q.pop(); inq[x]=0;
for(R II i=0;i<back[x].size();i++)
{
R II go=back[x][i];
if(dis_back[go]<dis_back[x]+nu[go]) {
dis_back[go]=dis_back[x]+nu[go];
if(!inq[go]) {
Q.push(go);
inq[go]=1;
}
}
}
}
}
int main()
{
// freopen("1.in","r",stdin);
scanf("%d%d",&n,&m);
for(R II i=1;i<=m;i++)
{
R II x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(R II i=1;i<=n;i++)
{
if(!DFN[i]) {
Tarjan(i);
}
}
// 缩点;
for(R II i=1;i<=n;i++)
{
for(R II j=head[i];j;j=aa[j].up)
{
R II go=aa[j].to;
if(belong[go]!=belong[i]) {
just[belong[i]].push_back(belong[go]);
back[belong[go]].push_back(belong[i]);
}
}
}
// 建正反边;
dfs_just(belong[1]);
dfs_back(belong[1]);
// 记录一、二类点;
spfa_just();
spfa_back();
// 计算权值;
for(R II i=1;i<=bit;i++)
{
if(in_just[i]) {
for(R II j=0;j<back[i].size();j++)
{
R II go=back[i][j];
if(in_back[go]) {
ans=max(ans,dis_just[i]+dis_back[go]);
}
}
}
}
// 枚举合法的边;
printf("%d\n",ans-nu[belong[1]]);
// 减去 1 多算的的权值;
exit(0);
}