题意:给定一张有向图,从1开始随便走最后回到1,有一次机会可以反向沿着某条边走一次,求最多能经过多少个点,(每个点最多对答案贡献一次)
如果不能反向走,那么答案就是1所在的强连通分量的大小
当我们反了一条边后,答案就是反边后含1所在强连通分量的环
如果我们断开我们所反的边和1,那么会形成两部分——从1所在强连通分量走出和回到1所在强连通分量
所以我们先缩点
再利用拓扑排序分别求出缩点后的1所在的点与其他点在正图和反图的最长链,记做f1[x]和f2[x] (x表示在新图里的编号)
我们所要反向的边一定是强连通分量之间的边
枚举我们所要走反向的边l,
假设l所连接的强连通分量是 a -> b
ans=max{f1[b]+f2[a],2*size[belong[1]]}
因为每个点只对答案贡献一次,所以最后要减去1所在连通分量的大小
uses math;
var
n,m,x,y,l,tt :longint;
time,top,ans :longint;
i :longint;
z,dfn,low :array[0..100010] of longint;
belong,size,que :array[0..100010] of longint;
last :array[0..100010] of longint;
pre,other :array[0..100010] of longint;
vis :array[0..100010] of boolean;
la,f,indu :array[0..2,0..100010] of longint;
pr,ot :array[0..2,0..100010] of longint;
ll :array[0..2] of longint;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure connect2(x,y,op:longint);
begin
inc(ll[op]);
pr[op,ll[op]]:=la[op,x];
la[op,x]:=ll[op];
ot[op,ll[op]]:=y;
end;
procedure dfs(x:longint);
var
p,q,cur:longint;
begin
inc(time);
low[x]:=time;
dfn[x]:=time;
inc(top);
z[top]:=x;
vis[x]:=true;
//
q:=last[x];
while q<>0 do
begin
p:=other[q];
if dfn[p]=0 then
begin
dfs(p);
low[x]:=min(low[x],low[p]);
end else
if vis[p] then low[x]:=min(low[x],dfn[p]);
q:=pre[q];
end;
//
if low[x]=dfn[x] then
begin
cur:=-1; inc(tt);
while cur<>x do
begin
cur:=z[top];
dec(top);
vis[cur]:=false;
belong[cur]:=tt;
inc(size[tt]);
end;
end;
end;
procedure rebuild;
var
i,p,q:longint;
begin
for i:=1 to n do
begin
q:=last[i];
while q<>0 do
begin
p:=other[q];
if (belong[i]<>belong[p]) then
begin
connect2(belong[i],belong[p],1); inc(indu[1,belong[p]]);
connect2(belong[p],belong[i],2); inc(indu[2,belong[i]]);
end;
q:=pre[q];
end;
end;
end;
procedure topsort(x:longint);
var
i,p,q,h,tl,cur:longint;
begin
f[x,belong[1]]:=size[belong[1]];
h:=0; tl:=0;
for i:=1 to tt do if indu[x,i]=0 then
begin
inc(tl); que[tl]:=i; indu[x,i]:=-1;
end;
//
while h<=tl do
begin
inc(h);
cur:=que[h];
q:=la[x,cur];
while q<>0 do
begin
p:=ot[x,q];
f[x,p]:=max(f[x,p],f[x,cur]+size[p]);
dec(indu[x,p]);
if indu[x,p]=0 then
begin
inc(tl); que[tl]:=p; indu[x,p]:=-1;
end;
q:=pr[x,q];
end;
end;
end;
procedure find;
var
i,p,q:longint;
begin
for i:=1 to tt do
begin
q:=la[1,i];
while q<>0 do
begin
p:=ot[1,q];
ans:=max(ans,f[1,p]+f[2,i]);
q:=pr[1,q];
end;
end;
end;
begin
read(n,m);
for i:=1 to m do
begin
read(x,y);
connect(x,y);
end;
for i:=1 to n do if dfn[i]=0 then dfs(i);
//
rebuild;
for i:=1 to tt do f[1,i]:=-maxlongint div 10;
for i:=1 to tt do f[2,i]:=f[1,i];
topsort(1);
topsort(2);
//
ans:=2*size[belong[1]];
find;
writeln(ans-size[belong[1]]);
end.
——by Eirlys