题目描述
输入
输出
样例输入
样例输出
(1)、解题思路:
本题很直观的就是想找到一个价格最低和一个价格最高点(满足由起点能到达,且又可顺序到达终点),找最低价格的点可以这样来处理,从源点开始找到所有点的最低价格(某个顶点的最低价格就是从源点到该所有可能路径上的价格最低的点),最后枚举卖出的点,并且判断该点是否可以到达即可。此外,由于数据规模较大,一般的邻接矩阵难以承受,因此采用动态数据结构邻接表。但是本题有环,处理时还有几个细节问题:
1.由于是最后要判定所有的顶点是否可以到达终点,因此不妨将所有的边反向,由终点出发判断终点可以到达那些顶点就可以了,并做上标记。这样也就要求在读入边的时候必须反向再储存一次。
2.用SPFA求某个顶点的最低价格时,对SPFA进行了改进。由SPFA的原理可以知道,该算法可以处理环的问题,但是要求最短路径的长度是可以收敛的,也就是说不能在图中存在负权。该题目满足此要求。SPFA是用来求最短路径的算法,在此对其改进,来求路径上最小价格的点
(2)、代码详解:
program zuiyoumaoyi;
type point=record
other,pre:longint
end;
var p:array[0..500000]of point;
last:array[1..100000]oflongint;
max,min,cost:array[1..100000]of longint;//最大差价,最低价,价格
q:array[1..1000000]oflongint;//队列
v:array[1..100000]ofboolean;//判断是否入队
n,r:longint;
procedure build(a,b:longint);//建立两城市之间的关系
begin
inc(r);
p[r].other:=b;
p[r].pre:=last[a];
last[a]:=r;
end;
procedure init;
var i,m,x,y,z:longint;
begin
readln(n,m);//读入城市数和道路数
for i:=1 to n do
begin
read(cost[i]);//读入各城市价值
min[i]:=cost[i];//赋值为最小价值
end;
for i:=1 to m do
begin
readln(x,y,z);//读入各城市关系
build(x,y);//建立关系
if z=2 thenbuild(y,x);//两城市间双向通行
end;
end;
procedure spfa;
var head,tail,i,j,x:longint;
begin
fillchar(v,sizeof(v),false);
q[1]:=1;head:=1;tail:=1;v[1]:=true;//队列的初始状态,1为起点
while head<=tail do//队列不空
begin
x:=q[head];//取队首元素
j:=last[x];
whilej<>0 do
begin
i:=p[j].other;
if (min[i]>min[x])or(max[i]<=max[x]) then
begin
if min[i]>min[x] then min[i]:=min[x];//修改 最短路
if max[i]<max[x] then max[i]:=max[x];
if cost[i]-min[i]>max[i]then max[i]:=cost[i]-min[i];
if not v[i] then//拓展节点入队
begin
inc(tail);
q[tail]:=i;
v[i]:=true;
end;
end;
j:=p[j].pre;
end;
v[x]:=false;//释放结点,一定要释放,因为此节点有可能下次用来松弛其他节点
inc(head);//出队
ifhead>100000 then exit;
end;
end;
begin
init;
spfa;
writeln(max[n]);
end.
(3)、心得体会:
1.SPFA的功能与理解,不能仅仅局限于求最短路,而可以是图中某点到图中所有点的某种关系。比如说本题中可以用来求某点到1的所有路径中的Wmax。
2.实践出真知,只有亲自动手动脑练习,才能真正了解并掌握各类算法及代码的意义和用法。
3.学会善于利用网络资源。