分析
用tarjan·强连通分量找一个最小的环
代码
const
maxn=400100;
type
arr=record
x,y:longint;
next:longint;
end;
var
status:array[0..maxn] of boolean;
dfn,low:array[0..maxn] of longint;
sign:array[1..maxn] of longint;
edge:array[0..maxn] of arr;
ls:array[0..maxn] of longint;
zhan:array[0..maxn] of longint;
top:longint;
number:longint;
n,m,nm:longint;
shu,shu1:longint;
procedure add(x,y:longint);
begin
m:=m+1;
edge[m].x:=x;
edge[m].y:=y;
edge[m].next:=ls[x];
ls[x]:=m;
end;
procedure init;
var
i,j,k:longint;
begin
m:=0;
nm:=0;
fillchar(ls,sizeof(ls),0);
readln(n);
for i:=1 to n do
begin
read(j);
add(i,j);
end;
end;
function min(x,y:longint):longint;
begin
if x>y then exit(y)
else exit(x);
end;
procedure dfs(x:longint);
var
i,y:longint;
begin
inc(number);
inc(top);
zhan[top]:=x;
dfn[x]:=number;
low[x]:=number;
i:=ls[x];
while i<>0 do
begin
y:=edge[i].y;
if dfn[y]=0
then
begin
dfs(y);
low[x]:=min(low[y],low[x]);
end
else
if not status[y]
then low[x]:=min(dfn[y],low[x]);
i:=edge[i].next;
end;
if dfn[x]=low[x]
then
begin
nm:=nm+1;
repeat
sign[nm]:=sign[nm]+1;
status[zhan[top]]:=true;
top:=top-1;
until zhan[top+1]=x;
end;
end;
procedure main;
var
i:longint;
ans:longint;
begin
number:=0;
for i:=1 to n do
if dfn[i]=0 then dfs(i);
ans:=maxlongint;
for i:=1 to nm do
if (sign[i]<ans) and (sign[i]<>1)
then ans:=sign[i];
write(ans);
end;
begin
assign(input,'message.in');
assign(output,'message.out');
reset(input);
rewrite(output);
init;
main;
close(input);
close(output);
end.