洛谷 P1462 通往奥格瑞玛的道路

28 篇文章 1 订阅
27 篇文章 0 订阅

题目大意:
歪嘴哦想去奥格瑞玛即城市n,如果能到达的话,求在可行的所有路径中,交费最多的一次的最小值,不能到达输出“AFK”。

题解:
二分查找+spfa+队列:
1.找出城市中最小收费跟最大收费,然后对费用做2分查找。
2.对于二分的费用mid,做spfa,如果i可以到达奥格瑞玛且血量不超过歪嘴哦的血量就向前二分,不然到达就向后二分。
3.如果二分做完了,还不能到达就输出“AFK”,否则输出二分的结果。

var
  c,s,t,w,next,list:array [0..100001] of int64;
  a,d:array [0..10001] of int64;
  v:array [0..10001] of boolean;
  min,max,i,n,m,p,q,ans:longint;

function spfa(main:longint):boolean;
var
  head,tail,j:longint;
begin
  d[1]:=w[1]; for j:=2 to n do d[j]:=maxlongint;
  v[1]:=true; for j:=2 to n do v[j]:=false;
  head:=0;
  tail:=1;
  c[1]:=1;
  while head<tail do
        begin
           inc(head);
           j:=list[c[head]];
           while j>0 do
                 begin
                    if (a[t[j]]<=main) and (d[s[j]]+w[j]<d[t[j]])
                       then begin
                                d[t[j]]:=d[s[j]]+w[j];
                                if v[t[j]]=false
                                   then begin
                                           v[t[j]]:=true;
                                           inc(tail);
                                           c[tail]:=t[j];
                                        end;
                            end;
                     j:=next[j];
                end;
           v[c[head]]:=false;
        end;
  if d[n]<=p then exit(true);
  exit(false);
end;


procedure find(l,r:longint);
var
  mid:longint;
begin
  if l>=r then
     begin
        if spfa(l) then writeln(l)
                   else writeln('AFK');
        halt
     end;
  mid:=(l+r) div 2;
  if spfa(mid)
     then find(l,mid)
     else find(mid+1,r);
end;

begin
   readln(n,m,p);
   min:=maxlongint; max:=0;
   for i:=1 to n do
       begin
          readln(a[i]);
          if a[i]<min then min:=a[i];
          if a[i]>max then max:=a[i];
       end;
       for i:=1 to m do
           begin
              inc(q);
              readln(s[q],t[q],w[q]);
              next[q]:=list[s[q]];
              list[s[q]]:=q;
              inc(q);
              s[q]:=t[q-1]; t[q]:=s[q-1]; w[q]:=w[q-1];
              next[q]:=list[s[q]];
              list[s[q]]:=q;
           end;
      find(min,max);
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值