旅行

    xiaoxiao2025-10-29  7

    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个城市出发游览价值之和的最大值为多少。

    Hint

    对于20%的数据,N≤10; 对于40%的数据,N≤1000; 对于100%的数据,N≤200000,A[i]≤10000,F[i]≤N

    题解

    题目的难点在于求环 因为每个点只有一个出度和入度,那么环是不可能向任意一点发出边的 照例跑一遍tarjan求强联通分量也就是环,缩点,顺便也把环上的权值缩在环的编号上 dfs一下找最大值,记忆化搜索优化一下 据说拓扑排序可以过,也许吧 c++极限数据会爆栈,调了半天也就放弃了 为数不多的过100行的程序,留念一下标个tag

    Code

    type edge=record x,y,next:longint; end; arr=array[0..200000]of edge; var n,m,t,maxE,maxG,ans:longint; comp,low,dfn,ass,ls,wx,s,w:array[0..200000]of longint; v:array[0..200000]of boolean; flag:boolean; e,g:arr; function min(x,y:longint):longint; begin min:=x; if y<x then min:=y; end; procedure add(var q:arr;var max:longint;x,y:longint); begin inc(max); q[max].x:=x; q[max].y:=y; q[max].next:=ls[x]; ls[x]:=max; end; procedure tarjan(x:longint); var i,y:longint; begin inc(t); dfn[x]:=t; low[x]:=t; inc(s[0]); s[s[0]]:=x; v[x]:=true; i:=ls[x]; while i>0 do begin if dfn[e[i].y]=0 then begin tarjan(e[i].y); low[x]:=min(low[e[i].y],low[x]); end else if v[e[i].y] then low[x]:=min(low[x],dfn[e[i].y]); i:=e[i].next; end; if dfn[x]=low[x] then begin inc(comp[0]); repeat y:=s[s[0]]; comp[y]:=comp[0]; wx[comp[0]]:=wx[comp[0]]+w[y]; v[y]:=false; dec(s[0]); until x=y; end; end; procedure dfs(dep:longint); var i:longint; begin if ass[dep]>0 then begin ans:=ans+ass[dep]; exit; end; ans:=ans+wx[dep]; i:=ls[dep]; while i>0 do begin dfs(e[i].y); i:=e[i].next; end; end; procedure print; var i:longint; begin for i:=1 to n do begin ans:=ass[comp[i]]; if ans=0 then dfs(comp[i]); writeln(ans); ass[comp[i]]:=ans; end; end; procedure main; var i:longint; begin for i:=1 to n do if dfn[i]=0 then tarjan(i); fillchar(ls,sizeof(ls),0); for i:=1 to maxE do if comp[e[i].x]<>comp[e[i].y] then add(g,maxG,comp[e[i].x],comp[e[i].y]); maxE:=maxG; e:=g; end; procedure init; var i,x,y:longint; begin readln(n); for i:=1 to n do read(w[i]); for i:=1 to n do begin read(x); add(e,maxE,i,x); end; end; begin init; main; print; end.
    转载请注明原文地址: https://ju.6miu.com/read-1303648.html
    最新回复(0)