引出问题:
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]]