圖(3)--拓撲排序與關鍵路徑

fan_rockrock發表於2014-02-19

一.拓撲排序:

         1.定義: 拓撲排序可以理解為在有向圖無環圖AOV-網(Activity On Vertex :用圖的頂點表示活動,用弧表示活動之間的優先順序)中排成一個具有前後次序的線性序列。

         2.實現方式:

                     1). 輸入AOV網路。令 n 為頂點個數。
                     2). 在AOV網路中選一個沒有直接前驅的頂點, 並輸出之; 
                     3). 從圖中刪去該頂點, 同時刪去所有它發出的有向邊;
                     4). 重複以上 2、3 步, 直到:
                              全部頂點均已輸出,拓撲有序序列形成,拓撲排序完成

                              或者,圖中還有未輸出的頂點,但已跳出處理迴圈。這說明圖中還剩下一些頂點,它們都有直接前驅,再也找不到沒有前驅的頂點了。這時AOV網路中必定存                                 在有向環。

         3.演算法實現:                      

Status Topological Sort(ALGraph G)
{
	       //採用鄰接表儲存結構。若G無迴路,則輸出拓撲序列並返回OK,否則ERROR
	        FindInDegree(G,indegree); //對各頂點求入度indegree[0..vernum-1]
		InitStack(S);  //建零入度頂點棧
		for(i=0;i<G.vexnum; ++i)  
		   if(!indegree[i])  Push(S,i); //入度為0者進棧
	        count=0; //對輸出頂點計數
		while (!StackEmpty(S)) 
		{ 
                  Pop(S,i);       
		  printf(i,G.vertices[i].data);  
		  ++count;  //輸出i號頂點並計數        
	 	  for(p=G.vertices[i].firstarc; p; p=p->nextarc)
		     {          
			   k=p—>adivex;//對i號頂點的每個鄰接點入度減1           
			   if(!(--indegree[k]))  Push(S,k);   //若入度減為0,則入棧    
	              }//for   
		}//while   
		if(count<G.vexnum) return ERROR;//該有向圖有迴路  
		else return OK;
}//TopologicalSort 

二.關鍵路徑(操作帶權的有向AOE-網(Activity on Adge:用邊表示活動,邊上的權值表示活動持續的時間,頂點表示事件,事件表示在它之前的活動全都完成了)):

              1.關鍵路徑:完成工程最短的時間是從開始點(原點)到結束點(匯點)的最長路徑長度,路徑最長的路徑叫做關鍵路徑。

                        

               從v1到v9的最長路徑是(v1,v2,v5,v8,v9),路徑長度是18,故(v1,v2,v5,v8,v9)是一條關鍵路徑

               2.關鍵活動:l(i)=e(i),即最早開始時間和最晚開始時間相等的活動,關鍵路徑上的所有活動都是關鍵活動,因此提前完成非關鍵活動並不能提高工程的進度

                        例如:a6的最早開始時間e(a6)=5,最晚開始時間為l(a6)=8,意味著a6推遲3天完成也不會影響工程的進度,所以分析哪些是關鍵活動將有利於縮短整個工期。

                        推理怎樣求關鍵活動,即找l(i)=e(i)的活動:

                               設活動ai由弧<j,k>表示,其持續時間為dut(<j,k>),故有:

                                      e(i)=ve(j)             (ve(j)表示頂點事件j的最早開始時間)

                                       l(i)=vl(k)-dut(<j,k>)    (vl(k)表示頂點事件k的最晚開始時間) 

                         現在就要求ve(j)和vl(j),分兩步進行:

                                      (1)從ve(0)=0向前遞推:ve(j)=Max{ve(i)+dut(<i,j>)}      <i,j>屬於T(所有以第j個頂點為頭的弧的集合)

                                      (2)從vl(n-1)=ve(n-1) 向後遞推:vl(i)=Min{vl(j)-dut(<i,j>)}      <i,j>屬於S(所有以第i個頂點為尾的弧的集合)

                        於是我們可以得到求關鍵活動的思想如下:

                                   1)輸入e條弧(i,j),建立AOE網的儲存結構。
                                   2)從源點v0出發,令ve[0]=0按拓撲有序求其餘各頂點的最早發生時ve[i](1≤i≤ n-1)。如果得到的拓撲有序序列中頂點個數小於網中頂點數n,則說明網中                                      存在環,不能求關鍵路徑,演算法終止;否則執行步驟(3)。
                                   3 )從匯點vn出發,令vl[n-1]= ve[n-1],按逆拓撲有序求其餘各頂點的最遲發生時間vl[i] (n-2 ≥i≥ 2);
                                   4)根據各頂點的ve和vl值,求每條弧s的最早開始時間e(s)和最遲開始時間l(s)。若某條弧滿足條件e(s)=l(s),則為關鍵活動。                  

                3.利用上述思想解題:

                              

                   通過已經求得的各個頂點的ve(i)和vl(i)來求活動的e(i)和l()

                       

                       由於關鍵活動為e(i)=l(i),所以可得a1,a4,a7,a8,a10,a11為關鍵活動,相應的V1->V2->V5->V7->V9和V1->V2->V5->V8->V9為關鍵路徑

               4.總結求關鍵路徑的方法:

                       第一步(求每個頂點事件的最早開始時間): ve(源點) = 0 ;
                                                                                                   ve(j) = Max{ ve(i) + dut(<i, j>)}

                        第二步(求每個頂點的最晚開始時間):        vl(匯點) = ve(匯點);
                                                                                                   vl(i) = Min { vl(j) – dut(<i, j>)}

                         第三步(求每個活動的最早開始時間和最晚開始時間): e(s)= ve(i)
                                                                                                                         l(s)= vl(j) - dut(<i, j>)

相關文章