收费站(cost.pas/c/cpp)
【题目描述】
在某个遥远的国家里,有n个城市。编号为1,2,3,……,n。
这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城
市,需要花费一定的汽油。
开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间
的公路上没有任何的收费站。
小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满
的,并且她在路上不想加油。
在路上,每经过一个城市,她要交一定的费用。如果她某次交的费用比较多,她的心情就会变得很糟。所以她
想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到
了聪明的你,你能帮帮她吗?
【输入格式】
第一行5个正整数,n,m,u,v,s。分别表示有n个城市,m条公路,从城市u到城市v,车的油箱的容量为s升。
接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。
再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从
城市ai到城市bi,或者从城市bi到城市ai,需要用ci升汽油。
【输出格式】
仅一个整数,表示小红交费最多的一次的最小值。
如果她无法到达城市v,输出-1。
【输入样例1】
4 4 2 3 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
【输出样例1】
8
【输入样例2】
4 4 2 3 3
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
【输出样例2】
-1
【数据规模】
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
算法:二分答案+最短路
这道题算是挺简单的二分答案+最短路验证了。考试的时候没有时间做了,下来之后又做了一遍,发现还不错啊……
二分的时候我们二分那个最小费用(一开始把费用理解错了,理解成全部的费用了。。),然后做一遍SPFA,当经过某个点的费用大于这个最小费用就略过这条边,起点也是一样。
最后看终点的最短路,如果油超过了容量则不成立,不成立的话就往右找,否则向左找。
program cost;
const
maxn=10000;
maxm=10000000;
type
atp=record
y,next,dis:longint;
end;
var
n,m,st,ed,rest,min,max,tot,head,tail:longint;
a,first,v:array [0..maxn] of longint;
b:array [0..maxn] of boolean;
map:array [0..maxm] of atp;
que:array [0..maxm] of longint;
procedure init;
var
i,x,y,dis:longint;
begin
min:=maxlongint;
readln(n,m,st,ed,rest);
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
readln(x,y,dis);
inc(tot);
map[tot].y:=y;
map[tot].next:=first[x];
map[tot].dis:=dis;
first[x]:=tot;
inc(tot);
map[tot].y:=x;
map[tot].next:=first[y];
map[tot].dis:=dis;
first[y]:=tot;
end;
end;
function SPFA(x:longint):boolean;
var
t:longint;
begin
if a[st]>x then exit(true);
fillchar(b,sizeof(b),false);
fillchar(v,sizeof(v),100);
v[st]:=0;
que[1]:=st;
b[st]:=true;
head:=0;
tail:=1;
while head<tail do
begin
inc(head);
t:=first[que[head]];
while t>0 do
begin
if a[map[t].y]>x then
begin
t:=map[t].next;
continue;
end;
if v[que[head]]+map[t].dis<v[map[t].y] then
begin
v[map[t].y]:=v[que[head]]+map[t].dis;
if not b[map[t].y] then
begin
b[map[t].y]:=true;
inc(tail);
que[tail]:=map[t].y;
end;
end;
t:=map[t].next;
end;
b[que[head]]:=false;
end;
if v[ed]>rest then exit(true) else exit(false);
end;
procedure main;
var
l,r,mid:longint;
begin
l:=min;
r:=max;
if SPFA(max) then
begin
writeln(-1);
close(input);
close(output);
halt;
end;
while l<r do
begin
mid:=(l+r) shr 1;
if not SPFA(mid) then r:=mid else l:=mid+1;
end;
writeln(l);
end;
begin
assign(input,'cost.in'); reset(input);
assign(output,'cost.out'); rewrite(output);
init;
main;
close(input); close(output);
end.