黄海洋老师课件――图论算法

Download Report

Transcript 黄海洋老师课件――图论算法

数学应用实践
二 图论计算及其在物流管
理中的应用
2009
物流管理问题


最优选线问题:
一家石油公司要在9个贮藏设施之间建造若干
管道,以便从任一贮藏设施向其它贮藏设施传
输石油。试设计费用最低的管道网。
v1
1
4
2
v7
5
1
v5
4
v8
2
1
v6
4
2
3
v3
3
1
4
v4
5
v2
5
v9
最佳路径问题:
给定一个输运石油的线路网络,要将石油
从s点输运到t点。现有4个中转站,已知
有管道连接的两个中转站之间的距离。试
求一条由s到t的输油线路,使总距离最短。
v1
v3
9
5
8
s
2
5
7
9
v2
t
6
10
v4
一 图论简介
图 G=(V, E) 顶点集 V={v1,v2,v3,v4,v5},
边集 E={e1,e2,e3,e4,e5,e6,e7}
v2
e1
v1
e4
v4
e2
v3
e3
e5
e6
e7
v5
简单图:无自回环,无重边的图。
无向图:边没有指向。
有向图:边有指向。
顶点的度数:与一个顶点关联的边的个数;
若是有向图,则分为顶点的出度和入度。
无向图
有向图
v2
e1
v1
e2
v3
e4
e3
e5
e6
v5
e7
v1
v4
v3
t
s
v4
v2
如果两顶点v1与v2之间有边相连,则称顶点
vi1与顶点vi2邻接。
图G=(V,E)的邻接矩阵 A(G)=(aij), aij =
连接vi 与vj 的边数。
若G为无向图,则aij = aji 。
v2
e1
v1
e4
v4
e2
v3
e3
e5
e6
e7
0 1

1 0
A(G )   0 1

v5
1 0
0 1

v1 v2
0 1 0

1 0 1
0 1 1

1 0 1
1 1 0 
v3 v4 v5
v1
v2
v3
v4
v5
赋权图:对各个边赋予具有数值(权)的图。
数值表示路程、资源消耗、花费时间、成
本代价等等。
赋权图G=(V,E,w)的(费用)赋权矩阵定义
为W(G)=(wij)
d ij  (i, j )  E

wij  0 i  j
inf  (i, j )  E

赋权矩阵
v2
11
v1
v3
4
3
v4
5
2
6
7
v5
 0 11 

11 0 2
 2 0
W 
4  3
 5 6


4

3
0
7


5
6

7
0


v2
e1
e2 v3
e6
v5
v1
路(链): 以一顶点开始, 并
以一顶点结束的一个点与边
交错的序列.
若图的任意两个顶点都有一
条路连接, 则称为连通图.
当一条路的起点与终点重合
时, 称为回路(圈).
v2
e1
e2
v3
v1
e4
e3
v4
没有回路的图称为无圈图。连通的无圈图称为
“树”
图G=(V,E)的连通的无圈子图G’=(V’,E’) 称为G
的树, 又若V’=V, 即G’是包含G的所有顶点的树,
则称G‘为G的一棵生成树(支撑树).
定理:一个图是连通的当且仅当它有生成树。
树G(V,E)的性质:
树的边数等于其顶点数减“1”,即|E|=|V|-1;
 树的任意两个顶点之间恰有一条链相连接;
 在树中任意去掉一条边后,便得到一个不连通的图;
 在树中任意两个顶点之间添加
一条新边, 所得新图恰有一个圈。

赋权图G=(V,E,w)的一棵生成树
所有树枝上权的总和称为这棵树的权.
具有最小权的G的生成树
称为G的最小(生成)树。
二 最小生成树问题
在一个赋(边)权连通图G(V,E,w)中寻找一棵生成
树T=G(V,E1,w),E1E,使这棵树各边的权相加所
得和(也称为T的权)最小.称G中权最小的生成树
T*为G的最小生成树.
Prim算法、 Kruskal算法
应用:最优选线问题:
一家石油公司要在9个贮藏设施之间建造若干管道,
以便从任一贮藏设施向其它贮藏设施传输石油。试
设计费用最低的管道网。
Prim算法基本思想:
对赋权图G(V,E,w),任意选定一个顶点,取与
它相邻的权最小的边构成一个子树;再选择权
最小的与子树相邻的边扩展这棵树,继续这个
过程,经过|V|-1步获得一棵最小生成树。
v2
5
v1
2
7
v3
3
6
v4
2
v5
7
v7
1
2
6
4
v6
关键点:
为保证每添加一条边都构成树,所选的边应
该满足其一端在原来的子树顶点集V中,另
一端在V的余集Vc中,即在边集(V,Vc)中选
择,以避免圈的形成。
c
记与V中点相邻的点集为N(V),则(V,V )=(V,
VcN(V))。
为了在边集(V,Vc)中选到权最小的边:
先对每个顶点vVcN(V)取权最小的边(v,u), uV;
引入顶点赋值label(v)=min{w(v,u);uV},表示v
点到集合V的距离。
7
1
1
3
15
9
2
5
3
10
0
7
2
6
16
4

8
6
c
再对所有vV N(V)取距离最小者,
label(v*)=min{label(v);  vVcN(V)}。
将v*添入V,相应的边添入子树,就扩展了
树。
引入变量f表示顶点v是否属于子树顶点集V,
是则,f=1,否则 f=0。
1
1
3
1
2
6
1
5
3
9
2
7
15
10
0
7
7
16
4

3
2
5
3
9
8
6
15
10
0
7
2
6
16
4

8
6
Prim算法
第0步:k=0,任意选定一个顶点v0,令 V0=V\{v0}, T=;给顶点赋
值d(v0)=0,d(v)= vv0;(给定点标号f(v0)=1,f(v)=0 vv0;)
第k步:如果Vk= ; (或k=n-1)则结束,否则令k=k+1,
vVk-1N(Vck-1),
令d(v)=min{w(v,u);uVck-1}=w(v,u(v)),
取vkVk-1N(Vck-1), 使得
d(vk)=min{d(v), vVk-1N(Vck-1)},
令 Vk= Vk-1\{vk},(令f(vk)=1),
Tk-1=TkU{vk u(vk) w(vk,uk)}。
示意图
7

1
5

10
4
1
7
3
2
2
6
2
16
4
4
2
1
1

16
8
16
16
7
8

6
5
3
9
9
7
15
10
0
10

5

8
16
15
15
3

6
1
1
0
9

2
1
15
3
0
7

3
15
9
2
5
3
10
0
7
2
6
16
4

8
6
7
1
1
5
4
3
4
6
1
3
10
0
9
2
2
6
8
2
1
1
4
3
6
6
2
5
3
9
8
5
15
10
0
4
16
6
5
16
4
7
15
4
5
3
9
5
3
5
15
10
2
6
7
3
8
16
2
1
1
0
9
2
1
15
3
10
0
7
7
2
6
16
4
4
8
6
Prim算法程序:
边权矩阵
L=[1 2 5;1 3 2;2 4 2;2 5 7;3 4 7;3 6 4;4 5 6;
4 6 2;5 6 1;5 7 3;6 7 6];
v2
5
v1
2
7
v3
3
6
v4
2
v5
7
v7
1
2
6
4
v6
构造赋权矩阵a
m=7;%顶点个数n=size(L,1); %边数
a=inf*ones(7);
for i=1:n
a(L(i,1),L(i,2))=L(i,3);
a(L(i,2),L(i,1))=L(i,3);
end
for i=1:7
a(i,i)=0;
end
第0步:初始化
final=zeros(1,m);%待确定集每点标记为0
d=inf*ones(1,m);%记各顶点与子树邻接边上最小的
边权
aa=zeros(1,m);%aa(i)记录优选的与顶点i相邻顶点
p=ones(1,m-1); %每一步被选入确定集合中的顶点
tree=[];%树枝
p(1)=v0; %初始顶点v0
final(v0)=1;%确定集标记1
d(v0)=0;%对初始顶点v0赋值














for i=1:m-1%第i步选择
min=inf;
for k=1:m
if final(k)==0%只考虑待确定集中的点k
for j=1:m
if final(j)==1 && a(k,j)<=d(k)
%只考虑与确定集相邻的点
d(k)=a(k,j);
%替换点k到已确定集的距离
if d(k)<=min
min=d(k);
%选择到初始点距离最短的顶点,
p(i)=k; %第i步选入确定集的点
aa(k)=j;%点k与点j邻接边上权最小









end
end
end
end
end
tree=[tree [aa(p(i)) p(i) a(aa(p(i)),p(i))]'];
final(p(i))=true;%将选入确定集的点标记
end
weight=sum(tree(3,:));
第0步:初始化
function [weight,tree,p]=mintree2(w,v0)
n=size(w,1);%顶点个数
label=inf*ones(1,n);%标记各顶点与子树邻接边上最
小的边权
sb=1:n; labsb=inf.*sb;%待确定集,及其各点标记
father=zeros(1,n);%father(u)记录优选的与u连接的
顶点
p=ones(1,n);%每一步被选入确定集合中的顶点
tree=[];%树枝
u=v0;label(v0)=0;father(1)=v0;p(1)=v0;
sb(v0)=[];labsb(v0)=[]; %最小树树根从v0点开始
le=length(sb);k=1;
while le~=0
for i=1:le %考察待确定集中所有点
v=sb(i);
if w(u,v)<=label(v)
label(v)=w(u,v);
labsb(i)=label(v);father(v)=u;
end
end
[y,s]=min(labsb);
u=sb(s); %s是待定集中到确定集最近的点
sb(s)=[];labsb(s)=[]; %在待定集除去s
le=length(sb); k=k+1;p(k)=u;
tree=[tree [father(u) u w(father(u),u)]'];
end
weight=sum(tree(3,:));
Kruskal算法基本思想:
首先将G(V,E,w)的边按边权从小到大顺序
排列,然后从权最小的边选起,待选的边与
已选入的边只要不形成圈,就入选。选得
|V|-1条边,即得最小生成树.
v1
4
v2
1
2
1
4
v4
5
v7
5
v5
1
3
4
v8
2
1
1
1
2
1
1
v6
4
2
3
v3
5
v9
2
3
2
关键点:
为了避圈,对G的每个顶点v,根据已选入边
集E’的组成状况定义一个标号d(v),具有特
性: 保证已选定的边所在的联通块中各顶点
的标号一致.于是考虑下一条边时,只要这
条边两端点标号一致,就不入选,以避免圈
的形成。
Kruskal算法:
第0步:将G的m条边e1…em按权的递增顺序排成
序列ei1…eim: ,取k=0,E0=
d(vj)=j,j=1…n
第k步:如果|Ek|=n-1,则结束计算。否则,
k=k+1,
如果边eik两端点u,v的标号d(u)与d(v)相等,则
转下一步;否则,取Ek=Ek-1+{eik}.对Ek中一切
边e=(u,v),取d(v)=d(u)=min{d(u),d(v)}
三 最短路问题
在赋权图G(V,E,w)中寻找一条从指定的起点v0
到指定的终点vend的路,使得这条路的权最小。
最佳路径问题:
给定一个输运石油的线路网络,要将石油从s
点输运到t点。现有4个中转站,已知有管道连
接的两个中转站之间的距离。试求一条由s到t
的输油线路,使总距离最短。
最短路更一般的提法是,在赋权图
G(V,E,w)中寻找从起始点v0到其它任意顶
点的具有最小权的有向生成树。
最短路问题有解的必要条件是,在G中存在
根在v0的支撑树。
动态规划模型、Dijkstra迪杰斯特拉算法、
Floyd算法、线性规划模型。
Dijkstra算法的基本思想:
整体最优一定是局部最优,每次从一步之遥
中选择最优的边为下一步路的延伸,使得加
入该边所添入的顶点沿着已构成的线路到起
始点的路径最短。结果由近到远生成以起始
点v0为根的有向树。
v2
5
v1
2
7
v3
3
6
v4
2
v5
7
v7
1
2
6
4
v6
关键点:引入标记,
给顶点v赋值label(v) 用于记录第v个点到起始点v0
的最短距离
给顶点v标号f(v)用于表示第v个点是否已被用于构造
子树。
用p(i)记录第i步选入子树的顶点。
用T(i,:) 记录第i步选入子树的边。
用father(i)记录第i个点在去起始点v0的最短路上的
前一位点。(用father(i,j)记录在第j条路上第i个点在
去起始点v0的最短路上的前一位点, j=1,2,..k。 )
确定起点v0到终点vend的最短路:
path=[vend];
t= vend;
while t~=v0
t=father(t);
path=[t path];
end
从终点t= vend起选father(t)为第t个顶点
的前一位点,逐步向前,确定最短路。
Dijkstra算法
第0步:k=0,
对选定的起点v0,令 V0=V\{v0};
(f(v0)=1,f(v)=0 vv0;)
label(v0)=0,label(v)=vv0;
p(1)= v0, p(j)=0 j=2,..,n; k=0;
father(j)=1; j=1,..,n;
T=[];
第k步:如果Vk =(或k=|V|-1),则结束计算。否则,
c
令k=k+1, v Vk-1N(V k-1) (即 f(v)=0), 令
label(v)=min{label(v),label(vk-1)+w(v,vk-1)}
=label(vk*-1)+w(v,vk*-1)},
记 father(v)=k*-1;(有若干个k*,则分别记入fahter(v,j))
c
取vk Vk-1N(V k-1),
c
使得label(vk)=min{label(v), vVk-1N(V k-1)};
令Vk =Vk-1\{vk} ( f(vk)=1),
p(k+1)=vk T=[T; father(vk) vk ];
Dijkstra算法示意图
4

7

2
0
3
2
1


7
4
6
7
1
7
0
2
1
7

8
3
2
1
1

7
4
5
5
7
3
5
1
5
3
1

2

2
5
0
5

1
5
4
7
2
1
5
3
1
5
0
8
3
2
1
7
8
4
5
8
7
2
0
1
4
7
7
1
6
8
5
3
1
0
3
5
2
5
6
3
2
8
2
1
3
7
3
1
0
5
1
5
1
2
5
1
3
8
2
6
7
5
7
3
2
1
0
5
1
5
4
5
1
2
1
6
Floyd算法的基本思想
对一个具有有限个顶点的连通图,连接任意两点之间
的路径只有有限多种,可以从中选出最短者。
从赋权矩阵 D 0  w 开始,按递归公式构造矩阵
k 1
D  (dij )nn , 其中 dij  min{ dij , d
k
k
k
k 1
i k 1
k 1
 d k 1 j }
d ijk 表示顶点i与j点之间直接或只经过顶点1,..,k中
转的最短路径的长度。
于是,d ijn 表示顶点i与j点之间直接或经过任何顶点中
转的最短路径的长度。
关键点
注意到,如果dijk=dik-1k-1+dk-1jk-1,则k-1是
连接i与j最短路径上的紧接在i后面的点。
记 pijk=pik-1k-1,构造后继点矩阵Pk=(pijk)。
P0 =(pij0)表示没有中转的后继点矩阵,如i
与j相邻,则pij0=j,否则定义pij0=0。
pijn表示从i到j最短路径上的紧接着i的后续
点。
Floyd算法
第0步:令k=0, D0=w, P=(pij) 如果
wij=inf,则 pij=0,否则pij=j。
第k步:如果k>n,则结束计算。否则,
k=k+1,i,j,
如果dik-1+dk-1j>=dij 则进入下一步。
否则dijdik-1+dk-1j且pijpik-1 即更新
D和P后,再进入下一步。
线性规划模型
模型
Min wijxij
jxsj=1
ixit=1
ixij-jxji=0
xij{0,1}
is it
练习:





实现最短路的Dijkstra算法
完成1997 B 题截断切割
实现最短路的线性规划模型
完成2007B乘公交,看奥运第一问。
将本单元提出到的各种算法编程实现。
1997 B 题截断切割
某些工业部门,如贵重石材加工等,采用截断切
割的加工方式,这里的截断切割,是指将物体沿
某个切割平面分成两部分,从一个长方体中加工
一个已知尺寸,位置预定的长方体(这两个长方
体的对应面是平行的),通常要经过6 次截断切割
。设水平切割单位面积的费用是垂直切割单位面
积费用的r 倍,且当先后两次垂直切割的平面,不
管它们之间是否穿插水平切割,不平行时,因调
整刀具需额外费用。
试为这些部门设计一种安排各面加工次序(称…
切割方式)的方法,使加工费用最少(由工艺
要求,与水平工作台接触的长方体底面是事先
指定的),详细要求如下:
1> 需考虑的不同切割方式的总数。
2> 给出上述问题的数学模型和求解方法。
3> 试对某部门用的如下准则做出评价,每次选
择一个加工费用最少的切割面进行切割。
4> 对于 e=0 的情况有无简明的优化准则。
5> 用以下实例验证你的方法:
待加工长方体和成品长方体的长,宽,高分别为
10,14.5,19 和3,2,4,两者左侧面,正面,底面
之间的距离分别为6,7,5(单位为厘米,垂直切割
费用为每平方厘米1 元,r 和e 的数据有4 组:
1) r=1, e=0;
2) r=1.5, e=0;
3) r=8, e=0;
4) r=1.5, 2 ≦ e ≦ 15 ;
对最后一组数据应给出所有最优解,并进行讨论.
分析




毛坏、成品均为长方体,且这两个长方体
的对应面是平行的,
切割费用与切割面积成正比,水平切割r
元/cm^2,垂直切割1元/cm^2, 换方向加调
整费e元
工作台水平接触长方体底面
第一次切割不计刀具调整费
模型



将加工过程中所有可能的状态用6维向量。6各
分量分别表示左右、前后、上下是否被切割,
是则取值1,否则取值0。例如,毛胚状态
(000000),成品状态(111111),已切除右侧,
前面和下面的毛胚状态为(011001)。
将 一个状态表示为一个顶点,共有2^6=64个顶
点。
从一个状态经切割转移到另一个状态,构成一
条有向边,切割费用为该边的权。
从毛胚(000000)到成品(111111)的有向路代
表了一个切割过程,有向路的权就是加工
费用。
于是,最小费用切割问题的数学模型:
求赋权有向图G=(V,E,w)从顶点(000000)到
顶点(111111)的最短路。
进一步,如果只考虑平行切割边距大者先切割,
足以保证切割面积最小,并可用3维数组代替6维
数组,(x,y,z)分别表示左右、前后、上下状态,未
被切割取值0,边距大的部分已被切割取值1,两
边都切割好取值2。这样顶点个数为3^3=27.
于是,最小费用切割问题的数学模型:
求赋权有向图G’=(V’,E’,w’)从顶点(000)到顶点
(222)的最短路。
a0=[10 14.5 19];%毛胚的长、宽、高
a1=[3 2 4];%成品的长、宽、高
d1=[6 7 9];%左、前、底的边距
r=1;e=0;
d2=a0-a1-d1;%右、后、上的边距
切除后a=(a(1) a(2) a(3))
水平面积a(1)*a(2),垂直面积 a(1)*a(3)或a(2)*a(3)
程序片段
%构造顶点集
vertices=[];
for i=0:2
for j=0:2
for k=0:2
vertices(size(vertices,1)+1,:)=[i j k];
end
end
end
构造边权矩阵:
元素w(u,v) k0{1,2}上切左右还是前后
function w=weight(u,v,vertices,a0,a1,d1,r,e,k0)
w=0; v1=vertices(u,:);v2=vertices(v,:);
d2=a0-a1-d1;%右、后、上切除厚度
a=a0;
temp1=norm(v2-v1,2);temp2=sum(v2-v1);
if temp1~=1 || temp2~=1
w=inf; %v2不是对v1做且只做了一次切割而得的状态
else
for k=1:3
if v1(k)>0
switch v1(k)
case 1 %v1(k)=1厚边被切割剩下的尺寸
a(k)=a0(k)-max(d1(k),d2(k));
case 2 %v1(k)=2薄边被切割剩下的尺寸
a(k)=a0(k)-d1(k)-d2(k);%刚好等于a1(k)
end
end end
k=find(v2-v1);
if k==3
w=a(1)*a(2)*r;%水平切割费用r倍,
else
w=a(1)*a(2)*a(3)/a(k)*(1+norm(k0-k,1)*e);
k0=k;%垂直切割换方向加额外费用e,
end end