(数据结构)关键路径和最短路径

关键路径(AOE)

AOE和AOV的区别
AOV网和AOE网的不同:
它们都是用来对工程建模的,但它们还是有很大的区别,主要体现在AOV网是顶点表示活动的网,它只描述了活动之间的约束关系,而AOE网是用有向边表示活动,边上的权值表示活动持续的时间。AOE网是建立在AOV网基础之上(活动之间约束关系没有矛盾),再来分析完成整个工程至少需要多少时间,或者为缩短完成工程所需时间,应当加快那些活动等问题。

路径各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大路径长度的路径叫做关键路径,在关键路径上的活动叫做关键活动。
关键路径的几个参数:

(1)、事件的最早发生时间etv(earliest time of vertex):即顶点Vk的最早发生时间。

(2)、事件的最晚发生时间ltv(lastest time of vertex):即顶点Vk的最晚发生时间。也就是每个顶点对应事件最晚需要开始的时间,超出此时间将会延误整个工程。

(3)、活动的最早开始时间ete(earliset time of edge):即弧ak的最早开始时间。

(4)、活动的最晚开始时间lte(lastest time of edge):即弧ak的最晚开始时间,也就是不推迟工期的最晚开始时间。
寻找关键活动的流程:

  1. 首先,计算事件的最早时间,事件的最早时间=前面所有活动都完成
    在这里插入图片描述
  2. 根据求出的最早时间,可以求出每个事件的最晚时间
    在这里插入图片描述
  3. 依据事件的最早时间可以推出活动的最早时间,活动的最早时间,也就是该活动前事件的最早时间
  4. 依据事件最迟时间可以推导出活动的最迟时间,活动的最迟时间是其后一个事件发生的最迟时间减去该活动需要的时间。
  5. 活动的最迟时间和最早时间相等,则说明该活动是关键活动
    例子:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

最短路径:

Dijkstra(狄克斯特拉)算法
该算法能解决给定顶点到图中所有其他顶点的最短路径。其有一个限制是:图中所有边的权值不能为负数。
为什么不能为负数的原因:因为dijkstra用了贪心的思想,每次选取的是当前最短的边进行松弛,当边都是正权时,松弛后边权一定比当前最短边大,所以满足贪心的条件,有了负边后,可以通过无数次循环经过负边,得到最短路径,而这并不满足贪心的条件所以不能用dijkstra计算带有负边的单源最短路。

算法的基本思想是:对于给定的顶点a,将其放入顶点集合U中,然后找到以顶点集合U中的点为顶点的所有边中权值最小的边,将这条边的终点也加入到顶点集合U中,然后更新从给定点a到顶点集合U中能够直接关联到的顶点的已知最短路径的值;重复以上步骤,直到顶点集合U中包含所有n个顶点。

此外,如果这时还有未加入到U中的顶点,说明原图不连通。

例子如下,求解一个带权有向图中从顶点a出发到各个顶点的最短路径:

(1)图1中,只有a在集合U中,这时有两条边界边分别到顶点c和d

(2)图2中,选择距离a最近的d加入U并标记相应的边,标出新发现的到顶点e的边界边

(3)图3中,选择候选边界边中最短的边(a,c),并将c点加入集合U,此时又增加了3条新的边界边。此时,路径(a,c, e)比之前的路径(a,d,e)更近,所以更新到达e点的最短路径值。

(4)图4中,选择候选边界边中最短的边(c,e),并将e点加入集合U。

(5)图5中,此时,最短的候选边界边是(e,g),但是因为顶点b离a更近,所以先把顶点b加入集合U中。

(6)图6中,再按同样的方法加上最后两条边,即可得到所有的最短路径了。
在这里插入图片描述
单个原点的最短路径复杂度是O(n^2),全部原点是3次方。
Floyd算法
采用动态规划的思想
从任意节点i到任意节点j的最短路径有2种可能:1)直接从i直接到j,2)从i经过若干个节点k到j。所以,我们假设arcs(i,j)为节点i到节点j的最短路径的距离,对于每一个节点k,我们检查arcs(i,k) + arcs(k,j) < arcs(i,j)是否成立,如果成立,证明从节点i到节点k再到节点j的路径比节点i直接到节点j的路径短,我们便设置arcs(i,j) = arcs(i,k) + arcs(k,j),这样一来,当我们遍历完所有节点k,arcs(i,j)中记录的便是节点i到节点j的最短路径的距离。
例子:
在这里插入图片描述
在这里插入图片描述
python实现:

import numpy as np

N = 4
M = 100
edge = np.mat([[0, 2, 6, 4], [M, 0, 3, M], [7, M, 0, 1], [5, M, 12, 0]])
A=edge[:]
path=np.zeros((N,N))
def Floyd():
    for i in range(N):
        for j in range(N):
            if (edge[i,j]!=M  and edge[i,j]!=0):
                ##构建路径矩阵,保留当前节点的前继
                path[i][j]=i
    print(path)
    for a in range(N):
        for b in range(N):
            for c in range(N):
                if A[b,a]+A[a,c]<A[b,c]:
                    A[b,c]=A[b,a]+A[a,c]
                    path[b][c]=path[a][c]
    print(A)

if __name__ == '__main__':
    Floyd()
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值