图——图的应用之最短路径,拓扑排序、关键路径
目录
最短路径:
定义:
问题抽象:在有向网中 A 点(源点)到达 B 点(终点)的多条路径中,寻找一条各边权值之和最小的路径,即最短路径。
最短路径与最小生成树的不同在于路径上不一定包含所有的顶点(即n个顶点),也不一定包含n-1条边。
两种常见的最短路径问题:
一、单源最短路径—用 Dijkstra(迪杰斯特拉)算法
两点间最短路径
最短路径即为图中路径长度为14(权值之和为14)的这条。
二、所有顶点间的最短路径—用 Floyd(弗洛伊德)算法
它也可以用 Dijksta 算法:每次以一个顶点为源点,重复执行Dijkstra算法 n 次。
某源点到其他各点最短路径
Dijkstra(迪杰斯特拉)算法:
举例:
不能直达的(就是必须要经过T中的顶点才能到达的)记为无穷,然后找到最小的路径长度是8,即到v2,所以将v2加入到S
由于S中v2的加入,如果发现加入v2后到某顶点的的路径长度比没加v2之前的变短了,那就修改数组中的值,否则数组中的值保持不变。比如说v3,在加入v2之前从v1不能直达v3,所以值为无穷,而当加入了v2之后,就能通过v2到达了,并且路径长度13比无穷小,所以修改数组中的值为13。这时仍然从上往下去找路径长度最短的13,是到v1,所以将v1再加入S中。
重复以上的操作
所以最短路径就为:v0->v2->v1->v3->v4->v6->v5。
算法思路:
Floyd(弗洛伊德)算法:
举例:
没有路径的(即值为0或无穷的)在路径表中不记录其路径。
加入A时,原本从C到B没有路径,现在可以从C到A再到B就有路径了。
再加入B时,从A到C通过B路径长度更短一些,所以修改表中的值。
再加入C时,从B到A通过C路径长度更短一些,所以修改表中的值。
路径表即为最短路径需要经过哪些点,比如表中B到A的最短路径就为B先到C再到A。
算法思想:
拓扑排序:
有向无环图(简称DAG图):
如:
解决方法:
举例:
先修课表示修该课程之前需要先修的课,比如C2(离散数学),修离散数学之前我们需要先修C1(程序设计基础)。
AOV网的特点:
例如:
C1是C5的前驱,C5是C1的后继
C1是C3的直接前驱,C3是C1的直接后继
拓扑排序的定义:
拓扑排序的方法:
举例:
重复上面这两步,直至全部顶点均已输出;或者当图中不存在无前驱的顶点为止。
步骤如下:
直到最后:
此时我们就得到了一个拓扑序列。
由于我们选择是随机的,所以一个AOV网的拓扑序列不是唯一的。
如:
我们发现一个规则:无论如何,C3一定在C8之前,也就是说,C3可以不再是C8的直接前驱,但是一定要在它的前面。
拓扑排序的应用:
这是因为,最后会只剩下这个:
因为在这个环当中我们找不到没有前驱的顶点,它们彼此是彼此的前驱。
关键路径:
定义:
把工程计划表示为边表示活动的网络,即AOE网,用顶点表示事件,弧表示活动,弧的权表示活动持续时间。事件表示在它之前的活动已经完成,在它之后的活动可以开始。
如:
比如图中v2可以表示为 A 活动结束了,也可以表示 B 活动或者 C 活动开始了。
例:
我们所关心的问题以及解决方法:
关键路径上的活动是影响整个工程进度的关键。
求解关键路径:
看不懂的话没有关系,来看下面:
求最早发生时间找最大值是因为:只有把这些活动都进行完了才能继续下一个事件,而进行完这些活动的关键就在于得把持续时间最长的那个活动也进行完。就比如说图中你需要把Vu、Vv、Vw、Vx这些活动同时进行,当然Vu肯定很快就能进行完,但是只有当耗时最长的Vx也进行完了的时候,Vj才能开始进行。
同理,求最晚发生时间找最小值也是一样,比如图中规定Vn需要在10点开工,那么如果是活动Vu的话,它最迟也应该在1点开工(因为它需要持续9个小时),而其他三个活动Vv、Vw、Vx最迟需要在2点、2点、5点开工,但是为了保证Vn能够在10点准时开工,就必须把最坏的情况都考虑进去,所以最迟也要1点开工,即Vu。
举例:
算ve是从源点往汇点算
算vl是从汇点往回算
以v5为例,从v1到v5有路径v1->v2->v5和路径v1->v3->v5,从v5到v9有路径v5->v7->v9和路径v5->v8->v9,我们已经知道找最早完成时间(即ve)需要找路径长度的最大值,所以它的最大值为6+1=7;我们也已经知道找最晚完成时间(即vl)需要找最小值,所以它的最小值为18-9-2=7;
以a2为例求 e 和 l,直接套公式就可以了。e(2)=ve(v1)=0,l(2)=vl(v3)-4=6-4=2。(其中 j 是连接 a2 的前一个顶点 v1,k是连接 a2 的后一个顶点 v3,Wj-k就是 a2 的权值4)。