apio2009 atm题解

        题目请自行百度.

        这道题和sort很像,甚至比sort还水.在此再次吐槽noip模拟题的难度,完全跟noip不是一个级别.

        先缩点,求最长路即可.又打了一遍tarjan,应该不会忘了吧.

Code:

{$M 10000000}
program main;
type int=longint;
var
        i,j,k,m,n,high,ans:int;
        dis,low,dfn,h,tail,w,s,b,a:array[1..500000]of int;
        ne,t:array[1..500000]of int;
        x,y,tot:int;

function min(x,y:int):int;
begin
        if x<y then exit(x)else exit(y);
end;

procedure dfs(x:int);var i,j:int;
begin
        inc(high);a[high]:=x;
        dfn[x]:=high;low[x]:=dfn[x];
        b[x]:=10009;j:=h[x];
        while j<>0 do begin
                i:=t[j];
                if b[i]=0 then begin
                        dfs(i);low[x]:=min(low[x],low[i]);
                end else if b[i]=10009 then begin
                        low[x]:=min(low[x],dfn[i]);
                end;
                j:=ne[j];
        end;
        if low[x]=dfn[x]then begin
                for i:=low[x]to high do begin
                        s[a[i]]:=x;b[a[i]]:=8;a[i]:=0;
                end;
                high:=low[x]-1;
        end;
end;

function relax(x,y:int):boolean;
begin
        if dis[y]>=dis[x]+w[y]then exit(false);
        dis[y]:=dis[x]+w[y];exit(true);
end;

function spfa(ss:int):int;var l,r:int;
begin
        l:=0;r:=1;a[r]:=s[ss];
        dis[s[ss]]:=w[s[ss]];
        repeat
                inc(l);i:=a[l];
                j:=h[i];b[k]:=0;
                while j<>0 do begin
                        k:=t[j];
                        if(k<>i)and(relax(i,k))and(b[k]<>998)then begin
                                inc(r);a[r]:=k;b[k]:=998;
                        end;
                        j:=ne[j];
                end;
        until l=r;
end;

begin
        assign(input,'atm.in');reset(input);
        assign(output,'atm.out');rewrite(output);
        read(n,m);
        for i:=1 to m do begin
                read(x,y);inc(tot);
                if h[x]=0 then tail[x]:=tot;
                t[tot]:=y;ne[tot]:=h[x];h[x]:=tot;
        end;
        for i:=1 to n do read(w[i]);
        for i:=1 to n do if b[i]=0 then dfs(i);
        for i:=1 to m do t[i]:=s[t[i]];
        for i:=1 to n do if s[i]<>i then begin
                ne[tail[s[i]]]:=h[i];h[i]:=0;
                tail[s[i]]:=tail[i];w[s[i]]:=w[s[i]]+w[i];
        end;
        read(x);spfa(x);
        read(m);ans:=0;
        for i:=1 to m do begin
                read(x);
                if dis[s[x]]>ans then ans:=dis[s[x]];
        end;
        write(ans);
        close(input);close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值