關鍵路徑(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