图论——数学建模中的应用和画图

目录

零.基础知识

一.作图

(1)网站作图(强烈推荐)

(2)matlab作图

1.无权图

2.有权图

3.有向图

二.最短路径问题

(1)Dijkstra算法

(2)Bellman-Ford算法

(3)Floyd算法

三.matlab实现

(1)求最短路径

(2)在图中高亮出最短路径

(3)返回任意两点之间的最短距离

(4)找给定范围内的所有的点


零.基础知识

%warning()警告函数

%disp()打印函数

%num2str()数字转字符

%zeros(n)初始化n*n的零矩阵

%:代表矩阵的所有行或者列,两侧放置数字则代表从a到b的所有行或列

一.作图

(1)网站作图(强烈推荐)

https://csacademy.com/app/graph_editor/

需要科学上网

基本语法

[起点] [终点] [权值]

(2)matlab作图

1.无权图

G = graph(起点向量,终点向量)

plot(graph,"linewidth",a)

set(gca,'XTick',[],'YTick',[]);% 不在图中显示横纵坐标

%a设置线的宽度

% 编号必须从1开始编号,默认编号连续

% 起点向量s=[]

如果点是字符串,用元胞数组

% 起点向量s={"   "}

2.有权图

多出一个w权值数组

G=graph(s,t,w)

plot(G,'EdgeLabel',G.Edges.Weight,'linewidth',2)

3.有向图

G=digraph(s,t)

二.最短路径问题

  • 权重邻接矩阵

规定对角线上元素均为0,不存在的权重均为Inf正无穷

  • 最短路径

最短路径上的所有子路径都是起点到该点的最短路径

(1)Dijkstra算法

分为已选顶点集合,未选顶点集合

缺点

可以用于有向图,但不能处理负权重

(2)Bellman-Ford算法

不再将结点区分为是否已访问的状态,因为该模型是利用循环来进行更新权重的,且每循环一次,算法都会更新所有的结点的信息。

缺点

Bellman-Ford算法不支持含有负权回路的图

https://blog.csdn.net/a8082649/article/details/81812000

https://www.bilibili.com/video/av43217121

  •  负权回路

存在一个圈,这个圈上所有的权值之和是负数,那这就是一个负权环,也叫作负权回路。

存在福泉回路的图是不能求两点间最短路的,因为只要在负权回路上兜圈子,那所得的最短路长度可以任意小。

(3)Floyd算法

https://www.bilibili.com/video/av54668527

可以得到任意两点之间的最短路径,而上述两种算法需要指定起点和终点

算法核心:三层循环,动态规划

for k in range(self.V):

    for i in range(self.V):

        for j in range(self.V):

            if self.D[i][k]+self.D[k][j]<self.D[i][j]:

                self.D[i][j]=self.D[i][k]+self.D[k][j]

                self.S[i][j]=self.S[i][k]

Floyd算法最后得到两个矩阵,一个是Distance Table距离矩阵,一个是Sequence Table次序矩阵(行坐标->列坐标需要先走到的节点).

matlab代码:可以计算出所有节点与节点的最短路径

Floyd_algorithm核心算法

% D是邻接权重矩阵

func [dist,path]=Floyd_algorithm(D)

n=size(D,1)

% 初始化dist 矩阵和path 矩阵

dist=D;

path=zeros(n);

for j=1:n

        path(:,j)=j;

end

for i=1:n

        path(i,i)=-1;

end

%算法部分

for k=1:n

        for i=1:n

                for j=1:n

                        if dist(i,k)+dist(k,j)<dist(i,j)

                                dist(i,j)=dist(i,k)+dist(k,j);

                                path(i,j)=path(i,k);

                        end

                end

        end

end



end

print_path函数

    function []=print_path(path,dist,i,j)

if i==j
    warning('起点和终点相同,请检查后重新输入')
    return;
end

if path(i,j)==j
    if dist(i,j)==Inf
        disp(['从',num2str(i),'到',num2str(j),'没有路径可以到达'])
    else 
        disp(['从',num2str(i),'到',num2str(j),'的最短路径为'])
        disp([num2str(i),'--->',num2str(j)])
        disp(['最短距离为',num2str(dist(i,j))])
    end
else 
    k=path(i,j)
    result=[num2str(i),'--->'];
    while k ~=j
        result=[result,num2str(k),'--->];
        k=path(k,j);
    end
    result=[result,num2str(k)];
    disp(['从',num2str(i),'到',num2str(j),'的最短路径为'])
    disp(result)
    disp(['最短距离为',num2str(dist(i,j))])
end

end

应用Floyd_algorithm

n = 9;  %一共九个节点
D = zeros(n);  
% 因为是无向图,所以权重邻接矩阵是一个对称矩阵
D(1,2) = 4; D(1,8) = 8; 
D(2,8) = 3; D(2,3) = 8;
D(8,9) = 1; D(8,7) = 6; 
D(9,7) = 6; D(9,3) = 2;
D(7,6) = 2; D(3,4) = 7; 
D(3,6) = 4; D(6,4) = 14;
D(4,5) = 9; D(6,5) = 10;
D = D+D';   % 堆成矩阵
for i = 1:n
    for j = 1:n
        if (i ~= j) && (D(i,j) == 0)  
            D(i,j) = Inf;   % 将非主对角线上的0元素全部变为Inf
        end
    end
end

%% 调用Floyd_algorithm函数求解
[dist,path] = Floyd_algorithm(D)

print_path(path,dist,1,5)

缺点:

所以限于计算机的算力,在点数比较少时采用Floyd算法

三.matlab实现

(1)求最短路径

[P,d]=shortestpath(G,start,end,'Method',algorithm]

% G:输入图对象

% start:起始点

% end:目标点

% algorithm:默认为auto,auto是matlab选择的最适合该图的算法 

% P:最短路径经过的结点

% d:最短距离

(2)在图中高亮出最短路径

myplot=plot(G,'EdgeLabel',G.Edges.Weight,'linewidth',2)

highlight(myplot,P,'EdgeColor','r')

(3)返回任意两点之间的最短距离

D=distances(G)

(4)找给定范围内的所有的点

[nodeIDs,dist]=nearest(G,s,d)

% 返回图形G中与节点s的距离在d之内的所有结点

% nodeIDs是符合条件的结点

% Dist是这些节点与s的距离
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值