【NOIP2011模拟9.17】旅行

    xiaoxiao2026-08-07  6

    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.
    转载请注明原文地址: https://ju.6miu.com/read-1310931.html
    最新回复(0)