数学建模学习笔记(七)——图论最短路问题

一、综述

本文主要根据图论的基本概念,介绍图论中常见的建模问题——最短路问题。同时,介绍了解决图论最短路问题的两种算法:Dijkstra(迪杰斯特拉)算法和Bellman-Ford(贝尔曼-福特)算法。

在此之前,需要具备基本的图论知识哦~~~

二、图论最短路问题

图论最短路问题指的是在带权重的图中,求出一条从一点节点到另一个节点的路径,使这条路径上的权重之和最小

三、几个简单的作图方法

1.CS Academy:
https://csacademy.com/app/graph_editor/
2. Matlab:
无向图:graph()函数
有向图:digraph()函数

四、Dijkstra(迪杰斯特拉)算法

  1. D i j k s t r a Dijkstra Dijkstra(迪杰斯特拉)算法描述
    假设未选取的节点集合未V,已选取的节点集合为S。
    -除起点外,其他节点初始距离为 ∞ \infty ,起点距离为0。
    -更新节点之间的距离(相邻接的节点距离即为权值,不相邻接的节点距离仍为 ∞ \infty )。
    -选取另一个未被选取过且距离最小的节点作为中转点,更新距离。(原距离 + 该节点和目标节点的权值 < 目标节点的原距离,则更新目标节点的距离为前者;否则不更新)。
    -重复第三步,直到到达目标节点。
    在这里插入图片描述

  2. 下面来看一个例子:
    有一个旅行者想要从 v 1 v1 v1 节点到 v 8 v8 v8 ,求出最短旅行路线。
    在这里插入图片描述

  3. 解决步骤
    第一步:初始化表格

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)000000000
    距离 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点-1-1-1-1-1-1-1-1-1

    第二步:从 v1 节点开始

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)100000000
    距离0 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1-1-1-1-1-1-1-1-1

    第三步:更新从 v1 可到达的节点的距离

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)100000000
    距离0631 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v1v1v1-1-1-1-1-1

    第四步:取距离最小的节点 v4 作为中转点,更新从 v4 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)100100000
    距离0631 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v1v1v1-1-1-1-1-1

    第五步:更新后的结果

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)100100000
    距离0631 inf ⁡ \inf inf11 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v1v1v1-1v4-1-1-1

    第六步:再取距离最小的节点 v3 作为中转点,更新从 v3 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)101100000
    距离0631 inf ⁡ \inf inf11 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v1v1v1-1v4-1-1-1

    第七步:更新后的结果(由于3 + 2(v3 到 v2 的距离)= 5 < 6,因此更新 v2 列的距离)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)101100000
    距离0531 inf ⁡ \inf inf11 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v3v1v1-1v4-1-1-1

    第八步:再取距离最小的节点 v2 作为中转点,更新从 v2 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111100000
    距离0531611 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v3v1v1v2v4-1-1-1

    第九步:再取距离最小的节点 v5 作为中转点,更新从 v5 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111110000
    距离0531611 inf ⁡ \inf inf inf ⁡ \inf inf inf ⁡ \inf inf
    父亲节点v1v3v1v1v2v4-1-1-1

    第十步:更新后的结果

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111110000
    距离0531610912 inf ⁡ \inf inf
    父亲节点v1v3v1v1v2v5v5v5-1

    第十一步:再取距离最小的节点 v7 作为中转点,更新从 v7 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111110100
    距离0531610912 inf ⁡ \inf inf
    父亲节点v1v3v1v1v2v5v5v5-1

    第十二步:再取距离最小的节点 v6 作为中转点,更新从 v6 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111111100
    距离0531610912 inf ⁡ \inf inf
    父亲节点v1v3v1v1v2v5v5v5-1

    第十三步:再取距离最小的节点 v8 作为中转点,更新从 v8 可到达的节点标号(注意比较与原距离的大小)

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111111110
    距离053161091215
    父亲节点v1v3v1v1v2v5v5v5v8

    第十四步:最终结果

    节点v1v2v3v4v5v6v7v8v9
    是否已被访问(0/1)111111111
    距离053161091215
    父亲节点v1v3v1v1v2v5v5v5v8

    可以从终点v8倒推: v 8 ⇐ v 5 ⇐ v 2 ⇐ v 3 ⇐ v 1 v_8 \Leftarrow v_5 \Leftarrow v_2 \Leftarrow v_3 \Leftarrow v_1 v8v5v2v3v1,这就是最短路径。将路径上的权值相加可以得出,最短路径的长度为:12(可以直接有 v8 那一列的距离得出),结果如图:
    在这里插入图片描述

  4. 若只考虑路径长度,而不考虑具体路径,还可以这样列表:

    v1v2v3v4v5v6v7v8v9
    0 ∞ \infty ∞ \infty ∞ \infty ∞ \infty ∞ \infty ∞ \infty ∞ \infty ∞ \infty
    $631 ∞ \infty ∞ \infty ∞ \infty ∞ \infty ∞ \infty
    $63 ∞ \infty 11 ∞ \infty ∞ \infty ∞ \infty
    $5 ∞ \infty 11 ∞ \infty ∞ \infty ∞ \infty
    $611 ∞ \infty ∞ \infty ∞ \infty
    $10912 ∞ \infty
    $10912 ∞ \infty
    $12 ∞ \infty
    $15

    加粗的数字即为从起点到各节点的最短路径长度。

  5. Dijkstra(迪杰斯特拉)算法的局限
    D i j k s t r a Dijkstra Dijkstra(迪杰斯特拉)算法可以用于解决无向带权图和有向带权图的最短路径问题。但是要求权重全是正数,不能使负数。为了解决带负权重的最短路径问题,我们可以采用 B e l l m a n − F o r d Bellman-Ford BellmanFord(贝尔曼-福特)算法来解决。

五、Bellman-Ford算法

贝尔曼-福特算法实际上处理的是具有负权重的有向图(且该有向图不能含有负权回路,因此函数负权回路的图可以在权重的回路中不断循环,路径长无穷小)

  1. 贝尔曼-福特算法简介
    更新规则:如果(A与B的距离 + A列表中的距离)< (B列表中的距离),那么我们就将B列表中的距离更新为较小的距离,并将B的父亲节点更新为A。

  2. 在 Matlab 中使用贝尔曼-福特算法
    M a t l a b Matlab Matlab 中调用命令:[P, d] = shortestpath(G, start, end [, 'Method', algorithm])
    输 入 参 数 : { G : 输入图对象 s t a r t : 起始的节点 e n d : 目标的节点 [ , ′ M e t h o d ′ , a l g o r i t h m ] : 可选参数,表示计算路径所使用的算法。默认为‘auto’ 输入参数:\left\{ \begin{aligned} &G:\text{输入图对象} \\ &start:\text{起始的节点} \\ &end:\text{目标的节点} \\&[, 'Method', algorithm]:\text{可选参数,表示计算路径所使用的算法。默认为‘auto’} \end{aligned}\right. G:输入图对象start:起始的节点end:目标的节点[,Method,algorithm]:可选参数,表示计算路径所使用的算法。默认为‘auto’

    输 出 参 数 : { P : 最短路径经过的节点 d : 最短距离 输出参数:\left\{ \begin{aligned} &P:\text{最短路径经过的节点} \\ &d:\text{最短距离} \end{aligned} \right. {P:最短路径经过的节点d:最短距离

    可 选 的 算 法 : { a u t o : 自动选择算法 u n w e i g h t e d : 广度优先计算,将所有便权重视为1 p o s i t i v e : Dijkstra算法 m i x e d : Bellman-Ford算法 可选的算法:\left\{ \begin{aligned} &auto:\text{自动选择算法} \\ &unweighted:\text{广度优先计算,将所有便权重视为1} \\ &positive:\text{Dijkstra算法} \\ &mixed:\text{Bellman-Ford算法} \end{aligned}\right. auto:自动选择算法unweighted:广度优先计算,将所有便权重视为1positive:Dijkstra算法mixed:Bellman-Ford算法

六、总结

  1. 根据图的类型确定算法:
    1. 无向带权图、有向带正权图——Dijkstra算法
    2. 有向带负权图(不含负权回路)——Bellman-Ford算法
  2. 根据具体的算法过程计算或者使用Matlab等工具计算。

如果有什么错误,请一定提出哦~~~请添加图片描述

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值