最短路转载
一、Bellman-Ford算法 最优性原理
它是最优性原理的直接应用,算法基于以下事实: l 如果最短路存在,则每个顶点最多经过一次,因此不超过n-1条边; l 长度为k的路由长度为k-1的路加一条边得到; l 由最优性原理,只需依次考虑长度为1,2,…,k-1的最短路。 l 单源最短路径(从源点s到其它所有顶点v); l 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图); l 边权可正可负(如有负权回路输出错误提示); l 差分约束系统(需要首先构造约束图,构造不等式时>=表示求最小值, 作为最长路,<=表示求最大值, 作为最短路。<=构图时, 有负环说明无解;求不出最短路(为Inf)为任意解。>=构图时类似)。 算法描述 l 对每条边进行|V|-1次Relax操作; l 如果存在(u,v)∈E使得dis[u]+w<dis[v],则存在负权回路;否则dis[v]即为s到v的最短距离,pre[v]为前驱。 时空复杂度 for i:=1 to |V|-1 do for 每条边(u,v)∈E do Relax(u,v,w); for每条边(u,v)∈E do if dis[u]+w<dis[v] Then Exit(False) 算法时间复杂度O(VE)。因为算法简单,适用范围又广,虽然复杂度稍高,仍不失为一个很实用的算法。 改进和优化 如果循环n-1次以前已经发现不存在紧边则可以立即终止; Yen氏改进(不降低渐进复杂度);SPFA算法 二、 SPFA算法 算法简介SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。 算法流程SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,算法大致流程是用一个队列来进行维护,即用一个先进先出的队列来存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出队首顶点,对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在队列中,则将其入队。经过有限次的松弛操作后,队列将为空,算法结束。SPFA算法的实现,需要用到一个先进先出的队列 queue 和一个指示顶点是否在队列中的标记数组mark。为了方便查找某个顶点的邻接点,图采用临界表存储。 算法代码Procedure SPFA;
Begin
initialize-single-source(G,s);
initialize-queue(Q);
enqueue(Q,s);
while not empty(Q) do begin
u:=dequeue(Q);
for each v∈adj[u] do begin
tmp:=d[v]; relax(u,v);
if (tmp<>d[v]) and (not v in Q) then enqueue(v);
end;
end;
End;
负环处理需要特别注意的是:仅当图不存在负权回路时,SPFA能正常工作。如果图存在负权回路,由于负权回路上的顶点无法收敛,总有顶点在入队和出队往返,队列无法为空,这种情况下SPFA无法正常结束。 判断负权回路的方案很多,世间流传最广、比较容易实现并且高效的方法是记录每个结点进队次数,超过|V|次表示有负权。 扩展阅读见:http://blog.sina.com.cn/s/blog_4f3b79d00100ao4z.html 三、 学以致用 POJ 1201 Intervals 差分约束系统 设S(i)为 0..i中在最终序列中的的整数个数。则约束条件如下: S(b)-S(a-1) >= c
注意本题求的是最小值, 即不是最短路, 而是最长路! Bellman_ford即可! POJ 1275 Cashier Employment 出纳员的雇佣 黑书上有详细讲解 POJ 1364 King 差分约束系统 这个题目构图之后, 只需要用bellman_ford判断是否有负圈. 构图方法: 首先进行转换:a[j]+...+a[j+m] = a[1]+...a[j+m] - (a[1]+...+a[j-1]) = sum[j+m] -
sum[j-1] >(<) ki. 差分约束只能全部是<=或者(>=). 第二步转换: sum[j+m]-sum[j-1] <= ki-1 或者 sum[j-1]-sum[j+m] <= -ki-1. 约束图构造好后就是简单的Bellman-Ford了! POJ 1716 Integer Intervals 是1201的简单版本, 贪心算法能够得到更好的效果. POJ 2983 Is the Information Reliable? 差分约束题, 处理一下等号的情况, 然后普通的Bellman_ford POJ 3159 Candies 最短路径 Bellman-Ford超时, Dijkstra算法可以高效解决, SPFA(队列)居然超时...SPFA修改为堆栈实现就过了. POJ 3169 Layout 差分约束 Bellman-Ford 和 SPFA 实现均可 POJ 3259 Wormholes 判断负权回路 TOJ 2976 Path 单纯的最短路径 可练习SPFA ZOJ 3033 Board Games 我做的第一道Bellman-Ford题目 首先,DFS判断可达性,不可达直接输出infinity结束,可达,bellman-ford判断是否存在负环,存在输出infinity,否则,输出最短距离。 |