Chaos is a ladde|

West11

园龄:11个月粉丝:1关注:1

图论基础:最小路径问题

图论基础:最小路径问题

概念

图是一种抽象出的数学概念。图论是欧拉在研究柯尼斯堡七桥问题开创的数学分支。

一个图通常用一个二元组表示, G=(V(G),E(G)),其中V是非空集,称为点集 (vertex set),对于 V(G)中的每个元素,我们称其为顶点 (vertex)节点 (node),简称;E(G) 为 V(G) 各结点之间边的集合,称为边集 (edge set)

当边有向时,称为有向图;当边无向时,称为无向图。

表示方法

一般我们用一个邻接矩阵来表示一张图。

https://picx.zhimg.com/80/v2-8f286139ce1976dc5b2516f3f026c22e_1440w.jpeg?source=d16d100b

添加图片注释,不超过 140 字(可选)

比如这张图,就可以表示为

A B C D E F
A 0 2 4 Inf Inf Inf
B 2 0 5 Inf Inf 4
C 4 5 0 1 3 Inf
D Inf Inf 1 0 3 Inf
E Inf Inf 3 3 0 1
F Inf 4 Inf Inf 1 0

邻接矩阵是对称的,对于没有直接相连的两个点,用Inf表示。

按照邻接矩阵的性质,它一定是对称的。

最短路问题

现有一个图的邻接矩阵,求从A到其他各点的最短距离。

最短路径问题有很多解法,可以用整数规划,蒙特卡洛等,但最好的算法是迪杰斯特拉算法(Dijkstra),

其基本思想是按距 (起点)从近到远为顺序,依次求得 到G各顶点最短的路径和距离,直到 (终点)。以下是算法步骤

  1. Let l(u0)=0,for vu0,let l(v)=,S0=u0,i=0.
  2. For every vSi¯(Si¯=VSi).  l(v)=minuSi{l(v)l(u)+w(u,v)}. Si+1=Siui+1
  3. If i=|V|1, stop.Else,i=i+1 and do step2 again.

代码实现:

function [mydistance, mypath] = dijkstra(a,sb,db) %a为邻接矩阵,sb起点,db终点
    n=size(a,1);% n个结点
    visited(1:n) = 0;% 都没有访问过
    distance(1:n) = inf;
    distance(sb) = 0;%自己到自己的距离为0
    visited(sb) = 1;u=sb;%更新一次,已经访问过自己。
    parent(1:n) = 0;%前驱节点初始化
    for i=1 : n-1
        id = find(visited == 0);%查找未曾访问过的点
        for v = id
            if a(u,v) + distance(u) < distance(v) %起点到u的距离加(u,v)的距离小于起点到v的距离的话
                distance(v) = a(u,v) + distance(u);
                parent(v) = u;
            end
        end
        temp = distance;
        temp(visited == 1) = inf; %已经标号的点的距离换为无穷,防止之前的点加入筛选。
        [t,u] = min(temp); %找到这一轮选取的点中距离最小的点, 顺便更新u
        visited(u)=1;
    end
mypath = [];
if parent(db) ~= 0 %如果有路
    t=db;
    mypath = db;
    while t ~= sb
        p=parent(t);
        mypaht = [p mypath];
        t = p;
    end
end
mydiatance = diatance(db);

迪杰斯特拉算法有一个小问题, 就是不能计算权重有负值的点。

SPFA(贝尔曼-福特算法)和弗洛伊德等算法可以解决这个问题,见最短路 - OI Wiki (oi-wiki.org)

MATLAB自带函数

这里讲一下matlab自带的计算最小路径的函数,它也可以计算有负边权的问题。

[P,d] = shortestpath (G, start, end, ['method', algorithm])
%method 为求解的算法,具体如下
%auto为默认算法,其中unweighted用于无权图, positive用于边权非负图
%unweighted BFS广搜求解(仅用于无权图)
%positive dijkstra算法,用于非负边权图
%mixed算法 用贝尔曼-福特算法求解(能算负边权)

用matlab画图可用graph函数绘制边权图(在2021以上matlab版本中,graph也可以绘制邻接矩阵图了)

G = graph(s, t, w);%s为起点,t为终点,w为权重
plot(G,'linewidth',2);
set(gca, 'XTick', [], 'YTick', []);%去掉数轴

%%绘制字符数串图
s={'北京','上海','南京'};
t={'上海','南京','北京'};
w=[10,20,30];
G = graph(s, t, w);
plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2);
set(gca, 'XTick', [], 'YTick', []);%去掉数轴

%% 用邻接矩阵绘图(biograph在2021版本后已经被ban掉了)
cmat = [0 1 0 0;
       1 0 1 1;
       0 1 0 0;
       0 1 0 0];
name = {'Node1', 'Node2', 'Node3', 'Node4'};
% 用digraph创建有向图
G = digraph(cmat, name);
% 用plot函数绘制图形
figure;
p = plot(G, 'Layout', 'circle'); % 用'circle'布局来尝试模拟'radial'效果。
% 进一步定制图形,例如设置节点颜色、大小等(可选)
p.NodeColor = 'r';
p.MarkerSize = 10;

分享一个CS的网站,可以帮助画图:Graph Editor (csacademy.com)

本文作者:West11

本文链接:https://www.cnblogs.com/cxy1114blog/p/18288098

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   West11  阅读(20)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起