引出問題:
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]]