数学建模笔记 图论与网络优化

本文深入讲解了Dijkstra、Floyd、Prim和Kruskal算法,探讨了最短路径和最小生成树问题。通过手动实现和编程示例,帮助读者理解算法原理及应用场景。

前言

学图论算法的时候要被自己蠢哭了,第一次接触理解得很慢,所以花时间整理了一下,希望能加深一下印象。对于算法都是一些自己比较简单的理解,系统学习了数据结构后可能会有更深的思考。

Dijkstra算法

  • 算法描述
    在这里插入图片描述

  • 算法证明
    归纳法证明:假设对于每次进入永久标号集合S的点ui,依照它的前驱形成的都是最短路。第一个入S的点为起点u1,它的前驱就是u1,显然u1到u1的最短路就是u1->u1,长度为0.假设第n个入队的点满足假设,那么对于第n+1个入队的点v来说,利用反证法,如果d[u1,v]不是u1到v的最短路径,存在另一条更短的路径,那么记该路径最后一个属于S的点为x,x经过若干个点最后到达v,记y是x的后继,那么d[u1,v]<=d[u1,y],(若d[u1,v]>d[u1,y],那么这次入S的便是y而不是v),所以d[u1,y]+d[y,v]>=d[u1,v],矛盾。

  • 手动实现

接下来手动实现一下以下图从1到8的最短路径
在这里插入图片描述
画方框的即为选中的前驱,右侧为相应点前驱的更新 在这里插入图片描述
根据最终前驱得到最短路线:1->2->5->8在这里插入图片描述

  • 编程实现(matlab)
function pre=Dijkstra(A,s,e)
%A为邻接矩阵,s为起点,e为终点
num=size(A,1);
pre=zeros(1,num);%前驱集合
dist=zeros(1,num);%最短距离集合
V=[];%已选点集合
pre(1)=1;%初始化
dist(1)=0;
V(end+1)=1;
for i=2:num
    dist(i)=inf;
end
PRE=1;%最新前驱
while 1
    temp=zeros(1,num);
    for j=1:num
        temp(j)=inf;
    end
    for i=1:num
        if (~checkin(V,i))
            if dist(i)>dist(PRE)+A(i,PRE)
                pre(i)=PRE;
                dist(i)=dist(PRE)+A(i,PRE);
            end
            temp(i)=dist(i);
        end
    end
    PRE=find(temp==min(temp));
    V(end+1)=PRE;
    if length(V)==num
        break;
    end
end
route=[e];
while(e~=s)
    e=pre(e);
    route(end+1)=e;
end
route%输出路线(反向看)
function flag=checkin(set,x)
flag=0;
for i=1:length(set)
    if set(i)==x
        flag=1;
    end
end

clear;clc;
A=[0 2 1 8 inf inf inf inf;0 0 inf 6 1 inf inf inf;0 0 0 7 inf inf 9 inf;
0 0 0 0 5 1 2 inf;0 0 0 0 0 3 inf 9;0 0 0 0 0 0 4 6;0 0 0 0 0 0 0 3;0 0 0 0 0 0 0 0];
A=A+A';
pre=Dijkstra(A,1,8)

结果与手动结果一致

route =

     8     5     2     1


pre =

     1     1     1     6     2     5     4     5
  • 理解
    Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。但缺点是只能计算由固定起点开始的最小路径,而以下介绍的floyd算法可以计算任意两点间的最短路径。
    这个讲的蛮细致的:https://blog.youkuaiyun.com/lbperfect123/article/details/84281300

Floyd算法

  • 算法描述
    在这里插入图片描述

  • 算法证明
    如果vi,vj间存在最短路径,(该路径中的子路径也是相应起点和终点的最短路径,)对于这条路径中任意相邻的三个点v1,v2,v3,当算法遍历到v2时,则会连接起来v1,v3,得到v1到v3的最短路径v1->v2->v3。当所有点遍历完成后,vi到vj的最短路径也就被找到了。

  • 手动实现’
    传送门:https://blog.youkuaiyun.com/SweeNeil/article/details/88713677

  • 编程实现
    在这里插入图片描述

function route=Floyd(A,s,e)
num=size(A,1);
R=zeros(num,num);
for i=1:num
        for j=1:num
            R(i,j)=j;
        end
end
D=A;
for k=1:num
    for i
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值