图与网络模型及方法(一)

一.概论

        图论中的“图”是指某类具体事物和这些事物之间的联系。如果用点表示这些具体事物,用连接两点的线段表示两个事物的特定联系,就得到了描述这个“图”的几何形象。

        我们先通过一些例子来了解网络优化问题

        例 1 最短路问题(SPP-shortest path problem)

        一名货柜车司机奉命在最短的时间内将一车货物从甲地运往乙地。从甲地到乙地的 公路网纵横交错,因此有多种行车路线,这名司机应选择哪条线路呢?假设货柜车的运 行速度是恒定的,那么这一问题相当于需要找到一条从甲地到乙地的最短路。

        例 2 公路连接问题

        某一地区有若干个主要城市,现准备修建高速公路把这些城市连接起来,使得从其中任何一个城市都可以经高速公路直接或间接到达另一个城市。假定已经知道了任意两 个城市之间修建高速公路的成本,那么应如何决定在哪些城市间修建高速公路,使得总 成本最小?

        例 3 指派问题(assignment problem)

        一家公司经理准备安排 N 名员工去完成 N 项任务,每人一项。由于各员工的特点 不同,不同的员工去完成同一项任务时所获得的回报是不同的。如何分配工作方案可以 使总回报最大?

        例 4 中国邮递员问题(CPP-chinese postman problem)

        一名邮递员负责投递某个街区的邮件。如何为他(她)设计一条最短的投递路线(从 邮局出发,经过投递区内每条街道至少一次,最后返回邮局)?由于这一问题是我国管梅谷教授1960年首先提出的,所以国际上称之为中国邮递员问题。

        例 5 旅行商问题(TSP-traveling salesman problem)

         一名推销员准备前往若干城市推销产品。如何为他(她)设计一条最短的旅行路线 (从驻地出发,经过每个城市恰好一次,最后返回驻地)?这一问题的研究历史十分悠 久,通常称之为旅行商问题。

        例 6 运输问题(transportation problem)

        某种原材料有 M 个产地,现在需要将原材料从产地运往 N 个使用这些原材料的工 厂。假定 M 个产地的产量和 N 家工厂的需要量已知,单位产品从任一产地到任一工厂 的运费已知,那么如何安排运输方案可以使总运输成本最低?

         下面简要介绍图与网络的一些概念:

二.图与网络的基本概念

2.1 无向图

 2.2 有向图

 2.3 完全图、二分图

 2.4 子图

 2.5 顶点的度

 2.6 图与网络的数据结构

 

 

 

 2.7 轨与连通

 三.应用——最短路问题

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

Djikstra算法, 参考:

算法之迪杰斯特拉(dijkstra)非常详细介绍_PRML_MAN的博客-CSDN博客_迪杰斯特拉

python Dijkstra算法实现

def Dijkstra(graph, node_num, start_node,
             destination):  # graph 传 edges, node_num传包括起点在内的节点总数,
    chain = {}
    dist = []  # 用dist来记录各个节点更新的最短距离
    visit = [False]  # 用visit表示该节点是否被遍历过
    for i in range(node_num):
        dist.append(float("inf"))
        visit.append(False)
    node = start_node
    dist[node] = 0
    while 1:
        ls = []
        ls1 = []
        for i in range(node_num):
            if not visit[i]:
                ls.append(dist[i])
                ls1.append(i)
        minimum = min(ls)
        for i in ls1:
            if dist[i] == minimum:
                node = i
                break  # 找到visit为false节点中dist最短的作为本次node
        for i in range(node_num):
            if graph[node][i] != 'N':
                if dist[node] + graph[node][i] < dist[i]:
                    dist[i] = dist[node] + graph[node][i]
                    chain[i] = node
        visit[node] = True
        if visit[destination]:
            back = destination
            route = [back]
            while 1:
                if back == start_node:
                    break
                back = chain[back]
                route.append(back)
            route.reverse()
            return dist[destination], route

        其中graph传的是赋权图的邻接矩阵,其中两点不相邻在邻接矩阵中表示为‘N’,可以改成∞或0,只需在稍微改动即可。

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

        计算赋权图中各对顶点之间最短路径,显然可以调用 Dijkstra 算法。具体方法是:每次以不同的顶点作为起点,用 Dijkstra 算法求出从该起点到其余顶点的最短路径,反复执行 n −1次这样的操作,就可得到从每一个顶点到其它顶点的最短路径。这种算法的时间复杂度为 O(n^3) 。第二种解决这一问题的方法是由Floyd R W 提出的算法,称之为 Floyd 算法。

 

 例 9 某公司在六个城市c1 , c2 ,......., c6中有分公司,从ci 到cj 的直接航程票价记在下述矩阵的(i, j) 位置上。(∞表示无直接航路),请帮助该公司设计一张城市c1到其它城市间的票价最便宜的路线图。

 

Floyd算法的Matlab程序如下:

clear;clc;
n=6; a=zeros(n);
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25; a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25; a(5,6)=55;
a=a+a'; %邻接矩阵
M=max(max(a))*n^2; %M为充分大的正实数
a=a+((a==0)-eye(n))*M;
path=zeros(n);
for k=1:n
    for i=1:n
        for j=1:n
            if a(i,j)>a(i,k)+a(k,j)
                a(i,j)=a(i,k)+a(k,j);
                path(i,j)=k;
            end
        end
    end
end
a, path

结果:

 四.树

4.1 基本概念

        连通的无圈图叫做树,记之为T。若图G 满足V (G) =V (T ) ,E(T ) ⊂ E(G) ,则称T是G 的生成树。图G 连通的充分必要条件为G 有生成树。一个连通图的生成树的个数很多,用τ(G) 表示G 的生成树的个数,则有公式:

其中G − e 表示从G 上删除边e ,G ⋅ e 表示把e 的长度收缩为零得到的图

树有下面常用的五个充要条件。

定理 1

(i)G 是树当且仅当G 中任二顶点之间有且仅有一条轨道。

(ii)G 是树当且仅当G 无圈,且ε =ν −1。

(iii)G 是树当且仅当G 连通,且ε =ν −1。

(iv)G 是树当且仅当G 连通,且∀e∈ E(G) ,G − e 不连通。

(v)G 是树当且仅当G 无圈,∀e∉ E(G) ,G + e 恰有一个圈

4.2 应用——连线问题

        欲修筑连接 n 个城市的铁路,已知i城与j城之间的铁路造价为Cij,设计一个线路图,使总造价最低。

        连线问题的数学模型是在连通赋权图上求权最小的生成树。赋权图的具最小权的生成树叫做最小生成树。        

        下面介绍构造最小生成树的两种常用算法。

4.2.1 prim算法构造最小生成树

 例13 用prim算法求图5的最小生成树

用matlab求解图5最小生成树

% Prim算法
a=zeros(6); % 定义6*6的0元素初始矩阵
a(1,2)=6;a(1,3)=1;a(1,4)=5; % 对矩阵a的元素进行赋值
a(2,3)=5;a(2,5)=3;
a(3,4)=5;a(3,5)=6;a(3,6)=4;
a(4,6)=2;
a(5,6)=6;
a=a+a';a(find(a==0))=inf; % 值为0的元素,赋值为∞ 代表不联通的点
result=[]; % 空矩阵:存放最小生成树的点和边
p=1; % 从顶点1开始寻找最小生成树
tb=2:length(a); % 从第2个顶点到第6个顶点
while length(result)~=length(a)-1 % result边数≠顶点个数-1
    temp=a(p,tb);  %找到和第一个相邻的所有的边
    temp=temp(:); % 按列从左到右,将temp展开成向量
    d=min(temp); % 寻求向量中的最小值
    [jb,kb]=find(a(p,tb)==d); % [行标, 列标]:记录最小权值对应的位置
    % 最小边值可能不唯一,4-1、5-1的值 都为5
    % 可能有多个权值都为b的边,取第一个,行元素记为j、列元素记为k
    j=p(jb(1));k=tb(kb(1));
    result=[result,[j;k;d]]; % 记录到result矩阵中 5列的矩阵[行标:列标:权值]
    p=[p,k];
    tb(find(tb==k))=[]; % 将其他满足条件的权值删除
end
result

 result的第一、二、三行分别表示生成树边的起点、终点、权边集。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值