Description
X先生来到了一个奇怪的国家旅行。这个国家有N个城市,每个城市均有且仅有一个机场,但是这机场所有航班只飞往一个城市。每个城市有一个游览价值,第i个城市的游览价值为A[i]。
现在他想知道,从第i个城市出发,并只坐飞机飞往下一个城市,游览价值之和最多是多少(一个城市游览多次只计算1次游览价值)
Input
输入文件travel.in的第1行为一个正整数N。
第2行有N个非负整数A[i],表示了每个城市的游览价值。
第3行有N个正整数F[i],表示第i个城市的航班飞往的城市为F[i],可能出现F[i] = i的情况。
Output
输出文件travel.out包括N行,第i行包含一个非负整数,表示从第i个城市出发游览价值之和的最大值为多少。
分析
我们可以发现在一个环上的点的价值相同。
所以,可以把一个环缩成一个点,价值为环上的点的价值和。(用tarjan·强连通分量)
然后,来个简简单单的递推就好了。
代码
const
maxn=400100;
type
arr=record
x,y:longint;
next:longint;
end;
var
value,f:array[0..maxn] of longint;
memory:array[0..maxn] of longint;
status:array[0..maxn] of boolean;
dfn,low:array[0..maxn] of longint;
sign:array[0..maxn] of longint;
edge:array[0..maxn] of arr;
ls:array[0..maxn] of longint;
zhan:array[0..maxn] of longint;
backup: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
read(value[i]);
readln;
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);
shu:=shu+1;
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[zhan[top]]:=nm;
status[zhan[top]]:=true;
top:=top-1;
until zhan[top+1]=x;
end;
end;
procedure search(x:longint);
begin
shu1:=shu1+1;
if status[x] then exit;
status[x]:=true;
search(f[x]);
memory[x]:=memory[f[x]]+value[x];
end;
procedure main;
var
i:longint;
begin
number:=0;
for i:=1 to n do
if dfn[i]=0 then dfs(i);
for i:=1 to n do
backup[sign[i]]:=backup[sign[i]]+value[i];
value:=backup;
for i:=1 to m do
with edge[i] do
begin
if sign[y]<>sign[x] then f[sign[x]]:=sign[y];
end;
fillchar(status,sizeof(status),false);
for i:=1 to n do
begin
if not status[sign[i]]
then search(sign[i]);
writeln(memory[sign[i]]);
end;
end;
begin
init;
main;
end.