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个城市出发游览价值之和的最大值为多少。
Sample Input
8
5 4 3 2 1 1 1 1
2 3 1 1 2 7 6 8
Sample Output
12
12
12
14
13
2
2
1
Data Constraint
Hint
对于20%的数据,N≤10;
对于40%的数据,N≤1000;
对于100%的数据,N≤200000,A[i]≤10000,F[i]≤N。
分析:我们先进行一次拓扑排序。然后对于每个入度大于0的点,一定在环中。然后我们对每个环都进行计算,同一环中的数的价值相同。然后从环逆向枚举即可。
代码:
const
maxn=300001;
var
b,f,num,ru:array [0..maxn] of longint;
flag,h:array [0..maxn] of boolean;
i,j,n,x,t:longint;
procedure init;
var i:longint;
begin
readln(n);
for i:=1 to n do
read(f[i]);
for i:=1 to n do
begin
read(b[i]);
inc(ru[b[i]]);
end;
end;
procedure tpsort;
var i,l,head,tail,x,j:longint;
tp:array [0..200001] of longint;
begin
head:=0; tail:=0;
for i:=1 to n do
if ru[i]=0 then
begin
inc(tail);
tp[tail]:=i;
end;
repeat
if tail=0 then break;
inc(head);
dec(ru[b[tp[head]]]);
if ru[b[tp[head]]]=0 then
begin
inc(tail);
tp[tail]:=b[tp[head]];
end;
until head=tail;
x:=0;
for i:=1 to n do
begin
if (ru[i]<>0) and not h[i] then
begin
j:=b[i];
h[i]:=true;
while j<>i do
begin
h[j]:=true;
num[j]:=i;
f[i]:=f[i]+f[j];
j:=b[j];
end;
end;
end;
end;
procedure dfs(x:longint);
var t:longint;
begin
if h[b[x]]=false then
dfs(b[x]);
if num[b[x]]=0 then f[x]:=f[x]+f[b[x]]
else f[x]:=f[x]+f[num[b[x]]];
h[x]:=true;
end;
begin
init;
fillchar(h,sizeof(h),false);
tpsort;
for i:=1 to n do
begin
if h[i]=false then dfs(i);
if num[i]=0 then writeln(f[i])
else writeln(f[num[i]]);
end;
end.