读书笔记《数学建模算法与应用》第4-6章

注:章节序号与书中保持一致,省略部分为基础概念

4. 图与网络模型及方法

4.2 最短路问题

4.2.1 两个指定顶点之间的最短路径

Dijkstra 算法 function[mydistance,mypath]=mydijkstra(a,sb,db);

  • a 邻接矩阵
  • a(i,j) i-j的距离,可以是有向的
  • sb 起点的标号
  • db 终点的标号
  • mydistance 最短路距离
  • mypath 最短路路径

4.2.3 每对顶点之间的最短路径

Dijkstra 算法是时间复杂度是 O ( n 3 ) O(n^3) O(n3),第二种解决该问题的方法是Floyd 算法

Floyd 算法原理
最短路径-Floyd算法

Matlab 实现

% floyd.m
% 采用floyd算法计算图a中每对顶点最短路
% d是矩离矩阵
% r是路由矩阵
function [d,r]=floyd(a)
n=size(a,1);
% 初始化距离矩阵
d=a;
% 初始化路由矩阵
for i=1:n
    for j=1:n
        r(i,j)=j;
    end 
end 
r;

% Floyd算法开始
for k=1:n
    for i=1:n
        for j=1:n
            if d(i,k)+d(k,j)<d(i,j)
                d(i,j)=d(i,k)+d(k,j);
                r(i,j)=r(i,k);
            end 
        end 
    end
    k;
    d;
    r;
end
d
r

4.3 最小生成树问题

实际问题举例: 把无向图的每个顶点看作村庄,计划修建道路使得可以在所有村庄之间通行。把每个村庄之间修建道路的费用看作权值,那么我们就可以得到一个求解修建道路的最小费用的问题。

4.3.1 最小生成树

最小生成树特点:

  • 无回路,且包含原图中的n-1条边。
  • 包含原图中的全部顶点。
  • 边的权重和在所有其他生成树中最小。
  • 最小生成树存在,则该图一定连通。反过来一样,图连通,则最小生成树一定存在。

最小生成树:Prim算法
算法导论–最小生成树(Kruskal和Prim算法)

prim 算法构造最小生成树
操作方法: 从某一顶点出发,逐步构建,让一棵小树逐渐长大。

Kruskal 算法构造最小生成树
操作方法: 此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。

4.4 网络最大流问题

图割-最大流最小切割的最直白解读

实际问题举例: 将油从 s 运送到 t,中间的四个点为中转站,边的系数为管道容量。求 s 到 t 的最大流。
在这里插入图片描述

4.5 最小费用最大流问题

实际问题举例: 将油从 s 运送到 t,中间的四个点为中转站,边的系数为管道容量。求 s 到 t 的最大流。在该题干基础上,考虑不同管道上的运输费用也不相同,因为除了考虑输油管道的最大流外,还需要考虑输油管道输送最大流的最小费用。
在这里插入图片描述

4.6 Matlab 的图论工具箱

在这里插入图片描述
实例1: 求解 v 1 v_1 v1 v 1 1 v_11 v11 的最短路径及长度
在这里插入图片描述

clc,clear
a(1,2)=2;a(1,3)=8;a(1,4)=1;
a(2,3)=6;a(2,5)=1;
a(3,4)=7;a(3,5)=5;a(3,6)=1;a(3,7)=2;
a(4,7)=9;
a(5,6)=3;a(5,8)=2;a(5,9)=9;
a(6,7)=4;a(6,9)=6;
a(7,9)=3;a(7,10)=1;
a(8,9)=7;a(8,11)=9;
a(9,11)=2;a(9,10)=1;
a(10,11)=4;
a=a'; % matlab工具箱要求数据为下三角矩阵
[i,j,v]=find(a);  % 找出a中非0元素的行和列,分别存储在i,j中,并将结果放在v中
b=sparse(i,j,v,11,11)  % 构造稀疏矩阵
[x,y,z]=graphshortestpath(b,1,11,'Directed',false);  % 声明是无向图'Directed',false(或写0

[dist, path, pred]=graphshortestpath(G,S,T)

  • G是稀疏矩阵,S是起点,T是终点。
  • dist表示最短距离
  • path表示最短距离经过的路径节点
  • pred表示从S到每个节点的最短路径中,目标节点的先驱,即目标节点的前面一个节点。

实例2: (最短路算法)
在这里插入图片描述

  • 用四维向量表示状态,(人,狼,羊,菜),在此岸时取1,在对岸时取0。
  • 穷举所有可行状态,(1,1,1,1);(1,1,1,0) (1,1,0,1) (1,0,1,1) ;(1,0,1,0) (0,1,0,1);(0,0,1,0) (0,0,0,1) (0,0,0,0)
  • 构造赋权图,顶点为以上10种可行状态,状态间可以转换时边对应权重为1,反正则为 ∞ ∞
  • 问题转化为,初始点(1,1,1,1),结束点(0,0,0,0)的最短路径

本题难点在于邻接矩阵的表示,因为摆渡一次 就会改变现有的状态,为此再引入一个状态转移向量

  • 1表示过河,0表示未过河,状态转移有4种情况,人自己过河(1,0,0,0);人带狼(1,1,0,0);(1,0,1,0);(1,0,0,1)
  • 状态向量 与 转移向量运算:0+0=0;1+0=1;0+1=1;1+1=0
  • 如果可行状态+转移向量=可行状态,那么这两种可行状态对应的顶点就存在边。
% 4.10
clc,clear
% 可行状态行
a=[1 1 1 1;1 1 1 0;1 1 0 1;1 0 1 1; 1 0 1 0;0 1 0 1;0 1 0 0;0 0 1 0;0 0 0 1;0 0 0 0];
% 转移向量行
b=[1 0 0 0;1 1 0 0;1 0 1 0;1 0 0 1];
w=zeros(10); % 邻接矩阵初始化
for i=1:9 % 循环某顶点
    for j=i+1:10 % 循环某顶点的下一个顶点
        for k=1:4
            % xor() 异或运算,参数同为0/不为0 返回0,参数有01时 返回1
            if findstr(xor(a(i,:),b(k,:)),a(j,:)) % 判断初始顶点+状态转移 是否等于 下一个顶点
                w(i,j)=1; % 是的话,初始顶点-下一个顶点的边权重=1
            end
        end
    end
end
w=w';  % 下三角矩阵
c=sparse(w);  % 构造稀疏矩阵
[x,y,z]=graphshortestpath(c,1,10,'Directed',0);
h=view(biograph(c,[],'ShowArrows','off','ShowWeights','off'));  % 画出无向图
Edges=getedgesbynodeid(h);  % 提取句柄h种的边集
set(Edged,'LineColor',[0 0 0]);  % 边为黑色
set(Edged,'LineWidth',1.5);  % 边宽度1.5

实例3: (注意是有向图)
在这里插入图片描述

clc,clear
a=zeros(7);
a(1,2)=4;a(1,3)=2;
a(2,3)=3;a(2,4)=2;a(2,5)=6;
a(3,4)=5;a(3,6)=4;
a(4,5)=2;a(4,6)=7;
a(5,6)=4;a(5,7)=8;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值