Coursera - Algorithm (Stanford) - 课程笔记 - Week 13

Bellman Ford Algorithm

  • 单源最短路问题定义
    • 输入:有向图,已知各边长度,以及源点 s s s
    • 输出:计算从源点出发,到达图中个点最短路的长度
  • Dijkstra算法的问题
    • 对于存在负权边的情形,并不总是正确的
    • 并不是十分的分布式
  • 对于负权环的问题
    • 方案1:允许负权环的存在——得不到最短路
    • 方案2:要求无环最短路的计算——汉密尔顿遍历问题,NP完全问题
    • 方案3:允许负权边,但不允许负权环——BF算法
  • 目标
    • 计算所有顶点的单源最短路径长度——BF算法
    • 或者输出负环
  • 最优子结构
    • 图本身不好描述相对顺序
    • 路径的顺序比较明确
    • 问题大小的界定——路径的边个数
    • P P P:最多 i i i条边的限制下, s → v s \to v sv的最短路径长度
    • case 1:如果 P P P有最多 i − 1 i - 1 i1条边,那么其必然是 s → v s \to v sv的最短路径,拥有最多 i − 1 i - 1 i1条边
    • case 2:如果 P P P i i i条边,其中最后一条为 w → v w \to v wv,那么除去最后一条边的 P ′ P^\prime P即为 s → w s \to w sw i − 1 i - 1 i1条边的最短路
    • 最优子结构条件:允许环路(由于边数限制,不会无限循环),未达节点的最短路长度为 + ∞ + \infty +
    • L i , v = min ⁡ { L i − 1 , v , min ⁡ ( w , v ) ∈ E { L i − 1 , w + c w , v } } L_{i, v} = \min \{L_{i - 1, v}, \min_{(w, v) \in E} \{L_{i - 1, w} + c_{w, v}\}\} Li,v=min{Li1,v,min(w,v)E{Li1,w+cw,v}}
      • 一个子问题只需要 ( 1 + indegree(v) ⁡ ) (1 + \operatorname{indegree(v)}) (1+indegree(v))次搜索
      • 如果没有负权环,那么我们一定能在 n − 1 n - 1 n1条边内找到最短路,且不会有环路(环路只会增加路径长度),这种情况下和其他dp算法无异
  • 算法(不考虑负权环)
    • 初始化: A [ 0 , s ] = 0 A[0, s] = 0 A[0,s]=0 A [ 0 , v ] = + ∞ A[0, v] = +\infty A[0,v]=+
    • 循环: i = 1 , … , n − 1 i = 1, \dots, n - 1 i=1,,n1 v ∈ V v \in V vV
      • A [ i , v ] = min ⁡ { A [ i − 1 , v ] , min ⁡ } A[i, v] = \min \{ A[i - 1, v], \min \} A[i,v]=min{A[i1,v],min}
    • 时间复杂度: O ( m n ) O(mn) O(mn)(考虑最后实际的计算量只有 O ( n + n ∑ v indgree(v) ⁡ ) O(n + n \sum_v \operatorname{indgree(v)}) O(n+nvindgree(v))
    • 一个优化手段(保证达不到 O ( n 2 ) O(n^2) O(n2)):提前终止
      • 在某一次 i i i的迭代中,如果所有的 A [ i , v ] = A [ i − 1 , v ] A[i, v] = A[i-1, v] A[i,v]=A[i1,v]都成立,则终止程序
  • 如果输入的图确实有负权环怎么办?
    • 定理:图 G G G没有负权环,当且仅当在BF算法中, A [ n − 1 , v ] = A [ n , v ] A[n - 1, v] = A[n, v] A[n1,v]=A[n,v]
    • 结论:运行BF算法之后,检查 A [ n − 1 , v ] A[n - 1, v] A[n1,v] A [ n , v ] A[n, v] A[n,v]是否相同,已确定图中是否有无权环
    • 时间复杂度 O ( m n ) O(mn) O(mn)
    • 极端情况: s s s与任何其他点没有边相连,且其他点共同组成一个 负权环——加入一个零距离的虚拟节点
  • 空间优化
    • 实际上,我们在计算当前迭代最优解时只需要前一次迭代的结果
    • 空间优化可以达到 O ( n ) O(n) O(n)
    • 问题:如何在优化后的模式中重建最优解
    • 计算另外一个表 B B B,其中 B [ i , v ] B[i,v ] B[i,v]表示 s s s v v v的不超过 i i i条边上的最短路的倒数第二个节点(前序指针)——重建时,逆序沿着前序指针得到最优解
    • 可以利用这个逆序指针辅助检查负权环:迭代过程中 B B B检查到环,必然是一个负权环

All Pairs Shortest Paths

  • 问题定义

    • 输入:图(允许负权边)
    • 输出:计算所有点对之间的最短路长度 或者 报告图中存在负权环
  • 直接使用单源最短路算法?时间复杂度太高,含负权边的稠密图( n n n遍BF)可以达到 O ( N 4 ) O(N^4) O(N4)

  • Floyd-Warshall算法: O ( N 3 ) O(N^3) O(N3)复杂度

  • 最优子结构(不考虑负权环)

    • P P P为固定的源点 i i i和目标点 j j j,使用任意中间点 V ( k ) V^{(k)} V(k)
    • case 1:点 k k k不在 P P P中,那么 P P P是使用任意中间点 V ( k − 1 ) V^{(k - 1)} V(k1)的最短路
    • case 2:点 k k k P P P中,那么 P 1 P_1 P1 i i i k k k V ( k − 1 ) V^{(k - 1)} V(k1)的最短路, P 2 P_2 P2 k k k j j j V ( k − 1 ) V^{(k - 1)} V(k1)最短路
  • 算法

    • 三维数组 A A A A [ i , j , k ] A[i, j, k] A[i,j,k]表示使用节点 1 , … , k {1, \dots, k} 1,,k实现的 i i i j j j的最短路径
    • 初始化,对 i = j i = j i=j,置0;对 i ≠ j , k = 0 , ( i , j ) ∈ E i \neq j, k = 0,(i, j) \in E i=j,k=0(i,j)E,置 c i j c_{ij} cij;对 i ≠ j , ( i , j ) ∉ E i \neq j, (i, j) \notin E i=j,(i,j)/E,置 + ∞ +\infty +
    • 三重循环kij
      • A [ i , j , k ] = min ⁡ { A [ i , j , k − 1 ] , A [ i , k , k − 1 ] + A [ k , j , k − 1 ] } A[i, j, k] = \min \{A[i, j, k - 1], A[i, k, k - 1] + A[k, j, k - 1] \} A[i,j,k]=min{A[i,j,k1],A[i,k,k1]+A[k,j,k1]}
    • 时间复杂度 O ( N 3 ) O(N^3) O(N3)
  • 如何检查负权环?检查对角线,如果存在 A [ i , i , n ] < 0 A[i, i, n] < 0 A[i,i,n]<0,那么存在负权环

  • 解重建

    • 除了 A A A本身,还需要计算一个 B B B,表示 i i i j j j最短路上最大的标签
    • 在第二个情景,需要将 B B B重置为对应的 k k k
    • 得到最大点之后,在ik,kj之间继续寻找最短路
  • Johnson算法:归约到1次BF调用, n n n次Dijkstra调用

  • 重加权:对于节点 u u u v v v,定义其权重 p u p_u pu p v p_v pv,对于其边 < u , v > <u,v> <u,v> c e c_e ce,定义新的边权重 c e ′ = c e + p u − p v c_e^\prime = c_e + p_u - p_v ce=ce+pupv

    • 性质:对所有调整后的边,对 s s s t t t之间的所有路径,其路径权重只变化 p s − p v p_s - p_v pspv
    • 结论:上述重加权过程不会影响最短路结果
    • 思路:使用这种重加权方法对负权环进行处理——需要考虑点权重的获得
  • 点权重获得和重加权

    • 设置一个虚拟节点 s s s,其到所有既有节点的距离为0
    • 使用BF算法,计算 s s s到各点 v v v的最短距离
    • 该距离即为对应既有点的权重 p v p_v pv
    • 根据所有的点权重,定义 c e ′ = c e + p u − p v c_e^\prime = c_e + p_u - p_v ce=ce+pupv
  • 通过这样的方式,将所有的边的权重处理为非负,同时不改变最短路结果,在可行的情况下可以采用更快的Dijkstra算法

  • Johnson算法

    • 输入:可能含有负权环的有向加权边图 G G G
    1. 建立一个虚拟节点 s s s,其到达所有的点的距离均为0
    2. 在该新图上运行BF算法,计算从 s s s到达各店的最短路(在此阶段即可判断是否存在负权环并终止算法)
    3. 根据上述描述确定各点权重,并更新边权
    4. 接下来可以运行 n n n次Dijkstra算法计算最短路
    5. 在得到最短路之后,将最短路 d ′ ( u , v ) d^\prime(u,v) d(u,v),减去变化的权重得到最终得结果 d ( u , v ) = d p r i m e ( u , v ) − p u + p v d(u, v) = d^prime(u, v) - p_u + p_v d(u,v)=dprime(u,v)pu+pv
  • 时间复杂度(稀疏图): O ( n m log ⁡ n ) O(nm \log n) O(nmlogn)

  • 新边权非负性保证

    • 已知新点权 p v p_v pv p u p_u pu
    • P P P为到达 u u u的最短路,长度显然为 p u p_u pu
    • 针对边 ( u , v ) (u, v) (u,v),存在一条到达 v v v的路径 p u + c u v p_u + c_{uv} pu+cuv
    • 根据最短路性质 p v ≤ p u + c u v p_v \le p_u + c_{uv} pvpu+cuv
    • 则有 c u v ′ = p u + c u v − p v ≥ 0 c^\prime_{uv} = p_u + c_{uv} - p_v \ge 0 cuv=pu+cuvpv0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值