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

    xiaoxiao2021-03-25  132

    通往奥格瑞玛的道路

    题目背景

    在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量

    有一天他醒来后发现自己居然到了联盟的主城暴风城

    在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛

    题目描述

    在艾泽拉斯,有n个城市。编号为1,2,3,...,n。

    城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。

    没经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。

    假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。

    歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少。

    输入输出格式

    输入格式:

    第一行3个正整数,n,m,b。分别表示有n个城市,m条公路,歪嘴哦的血量为b。

    接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。

    再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。

    输出格式:

    仅一个整数,表示歪嘴哦交费最多的一次的最小值。

    如果他无法到达奥格瑞玛,输出AFK。

    分析:二分答案,对血量做spfa,每次可以在规定血量内到达就向前二分否则向后二分。

    代码

    const   maxn=50000; var   a,b,next,ls,s,c,d,p:array[0..maxn] of int64;   v:array[0..maxn] of boolean;   i,j,k,n,m,t1,t2,x,y,z,q,ans:longint; procedure init(w1,w2,w3,x:longint); begin   a[x]:=w1;   b[x]:=w2;   c[x]:=w3;   next[x]:=ls[w1];   ls[w1]:=x; end; function spfa(mon:longint):boolean; var   head,tail,t:longint; begin   for i:=1 to n do     d[i]:=maxlongint;   d[1]:=c[1];   head:=0;   tail:=1;   v[1]:=true;   s[1]:=1;   while head<tail do     begin       inc(head);       t:=ls[s[head]];       while t>0 do         begin           if (p[b[t]]<=mon) and (d[a[t]]+c[t]<d[b[t]]) then             begin               d[b[t]]:=d[a[t]]+c[t];               if not v[b[t]] then                 begin                   v[b[t]]:=true;                   inc(tail);                   s[tail]:=b[t];                 end;             end;           t:=next[t];         end;       v[s[head]]:=false;     end;   if d[n]>k then exit(false) else exit(true); 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 begin ans:=mid;find(l,mid);end else find(mid+1,r); end; begin   readln(n,m,k);   t1:=maxlongint;   for i:=1 to n do     begin       readln(p[i]);       if p[i]<t1 then t1:=p[i];       if p[i]>t2 then t2:=p[i];     end;   for i:=1 to m do     begin       readln(x,y,z);       inc(q);       init(x,y,z,q);       inc(q);       init(y,x,z,q);     end;   find(t1,t2); end.

    转载请注明原文地址: https://ju.6miu.com/read-6366.html

    最新回复(0)