這道題顯然要先 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);
}