关键路径(AOE网)python


引出问题:

1. 每个活动持续多少时间?

2. 完成整个工程至少需要多少时间?

3. 哪些活动是关键活动?

 

AOE网

AOE(Activity On Edge)网为一个带权的有向无环图。其中,以顶点表示时间,有向边表示活动,边上的权值表示活动持续的时间。正常情况下(网中无回路),AOE网中只有一个入度为0的顶点,称之为源点;有一个出度为0 的顶点,称之为终点。

AOE网的特点

1. 只有在某个顶点所代表 的事件发生以后,该顶点 引发的活动才能开始。2. 进入某事件的所有边代 表的活动都已完成,该顶 点代表的事件才能发生。

AOE网的存储:邻接矩阵

 

关键路径

定义:从源点到终点的路径中具有最大长度的路径为关键路径;关键路径上的活动称为关键活动

特点:(1) 关键路径的长度(路径上的边的权值之和)为完成整 个工程所需要的最短时间。(2) 关键路径的长度变化(即任意关键活动的权值变化) 将影响整个工程的进度,而其他非关键活动在一定范围内的变化不会影响工期。

求解思路:

e[i]  活动ai的最早开始时间;

l[i]   活动ai的最晚开始时间;

若缓冲时间/松弛时间/ 时间余量l[i]–e[i]  =0,则说明活动ai 为一个关键活动。

ee[k]  事件k的最早发生时间;

le[k]  事件k的最晚发生时间;

关系:ee[k] 和 le[k] 推出 e[i] 和 l[i],求出e[i]=l[i]的活动ai即关键活动

1. 计算事件k的最早发生时间ee[k]。

事件k的最早发生时间决定了由事件k出发的所有活动的最早开始时间;该时间是指从源点到顶点(事件)k的最大路径长度。

 

//计算方法
ee[0] = 0
ee[k]
= MAX { ee[j] + <j,k>的权}   <j;k>∈P{k} 

 

2. 计算事件k的最晚发生时间le[k]

事件k的最晚发生时间是指不影响整个工期的前提下事件k必须发生的最晚时间,它必须保证从事件k发出的所有活动的终点事件(k的后继事件)的最迟发生时间

//计算方法
le[n-1] = ee[n-1] le[k] = MIN { le[j]– <k,j>的权 }   <k,j>∈S{k}

3. 计算活动 i 的最早开始时间e[i]

活动i的最早开始时间实际上是事件k发生的最早时间,即只有事件k发生,活动i才能开始。

//计算方法 
e[i] = ee[k]

4. 计算活动 i 的最晚开始时间 l[i]

活动i的最晚开始时间是指不推迟整个工 期的前提下活动i开始的最晚时间。

//计算方法
l[i] = le[j]-<k,j>的权

5. 求出关键活动与关键路径

//计算方法: 
l[i] = e[i]

 

from queue import Queue,LifoQueue,PriorityQueue

n,m,s,t=map(int,input().split())
G=[[] for i in range(n+1)]
E=[[] for i in range(n+1)]
TE=[0 for i in range(n+1)]
TL=[2100000000 for i in range(n+1)]
TL[0]=0
In=[0 for i in range(n+1)]
Out=[0 for i in range(n+1)]
que=Queue(maxsize=0)
que.put(s)
que1=Queue(maxsize=0)
que1.put(t)
ans=[]
tmp=[0 for i in range(n+1)]
tmp[0]=s
def dfs(x,step=1):
    if x==t:
        ag=[]
        for i in range(0,step,1):
            ag.append(tmp[i])
        ans.append(ag)
        return
    for (u,w) in G[x]:
        if TE[u]==TL[u] and TE[u]==TE[x]+w:
            tmp[step]=u
            dfs(u,step+1)

for i in range(m):
    u,v,w = map(int,input().split())
    G[u].append((v,w))
    In[v]=In[v]+1
    E[v].append((u,w))
    Out[u]=Out[u]+1

while not que.empty():
    x=que.get()
    for (u,w) in G[x]:
        if TE[u]<TE[x]+w:
            TE[u]=TE[x]+w
        In[u]=In[u]-1
        if In[u]==0:
            que.put(u)

TL[t]=TE[t]
while not que1.empty():
    x=que1.get()
    for (u,w) in E[x]:
        if TL[u]>TL[x]-w:
            TL[u]=TL[x]-w
        Out[u]=Out[u]-1
        if Out[u]==0:
            que1.put(u)
            
dfs(s)
print("Dis=%d" % (TE[t]))    
for i in range(1, n+1):
    print("Node",i, end="")
    print(": TE= %3d" % (TE[i]),sep="",end=" ")
    print(" TL= %3d" % (TL[i]),sep="",end=" ")
    print(" TL-TE= ",TL[i]-TE[i],sep="")
print(sorted(ans,key=len))

输入

第一行是四个由空格隔开的整数 nn (节点个数), mm (边数), ss (源点), tt (终点)。此后的 mm 行,每行三个正整数 aa, bb, cc, 表示一条从节点 aa 到节点 bb 的一条长度为 cc 的边。(节点个数小于 1515 个)

输出

第一行输出关键通路的长度;

第二行到第 n+1n+1 行输出每一个顶点的 TETE, TLTL 和缓冲时间;

最后一行按Hint中所给格式,输出所有的关键通路。(若有多条,则根据关键通路中节点的个数排序进行输出,长度相同则按字典序排)

输入样例

9 15 1 9
1 2 3
1 3 2
1 4 4
2 5 4
2 3 0
3 5 4
3 6 4
3 4 2
4 7 5
5 9 6
5 7 3
5 6 0
6 8 3
8 9 1
7 8 1

输出样例

Dis=13
Node 1: TE=   0  TL=   0  TL-TE= 0
Node 2: TE=   3  TL=   3  TL-TE= 0
Node 3: TE=   3  TL=   3  TL-TE= 0
Node 4: TE=   5  TL=   6  TL-TE= 1
Node 5: TE=   7  TL=   7  TL-TE= 0
Node 6: TE=   7  TL=   9  TL-TE= 2
Node 7: TE=  10  TL=  11  TL-TE= 1
Node 8: TE=  11  TL=  12  TL-TE= 1
Node 9: TE=  13  TL=  13  TL-TE= 0
[[1, 2, 5, 9], [1, 2, 3, 5, 9]]


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM