關鍵路徑(拓撲排序)

2021-09-03 05:12:53 字數 1768 閱讀 4678

一.先給出幾個概念:

aoe-網:在帶權有向圖中頂點表示事物,有向邊表示活動,權表示活動持續的時間,則此有向圖稱為邊表示活動的網路。(activity on edge network)

(表示實際工程的aoe-網應該是無環的,且存在唯一入度為0的起始頂點(始點),以及唯一出度為0的完成頂點(終點)。)

利用aoe-網進行工程安排的估算,可以實現:

1.研究完成工程至少需要多少時間。

2.為縮短時間,應加快哪些活動的速度等問題。

用e(i)表示活動ai的最早開始時間,l(i)表示ai的最遲開始時間,e(i)=l(i)的活動稱為關鍵活動,由這些關鍵活動連線起來的路徑稱為關鍵路徑。

二.原理:

問題在於如何求e(i),l(i)。

若ve(i):事件i的最早發生時間;vl(i):事件最遲發生時間。(注意區分,活動表示邊,時間表示頂點,e(i),l(i)是對邊而言,ve(i),vl(i)是對頂點而言。

故可將對e(i),l(i)的計算轉化成對ve,vl的計算,而對ve,vl的計算可以通過拓撲排序的過程來實現。

e(i)=ve(j)          

l(i)=vl(k)-dut()

三.具體實現:

1.這裡對圖的儲存使用鄰接表,因為臨界矩陣很難實現,他無法體現邊的性質。

但需要對鄰接表做些改動:在表頭結點中加一項index,用於存放入度,並同時作為拓撲棧和逆拓撲棧。當然也可以不這樣做,但會耗費一定的空間。**如下:

#include#include#define len sizeof(tablenode)

using namespace std;

typedef struct node1tablenode;

typedef struct node2header;

2.建立鄰接表:

我這裡圖的頂點即採用0..n-1(n為頂點個數),但輸入邊的時候是輸的1..n,所以建立鄰接表需要減一。另外,在建立的同時需要計算出每個頂點的入度,為了後面拓撲排序時方便。**如下:

void buildadjlist(header (&a)[101],int n,int e)

}

3.求關鍵路徑:

這裡大概有3步:根據拓撲排序計算ve,根據拓撲排序的序列反向進行逆拓撲排序計算vl,輸出關鍵路徑。

具體的實現看如下的**:

void cpm(header (&a)[101],int n)

if(ve[x]dut)

ve[x]=ve[p]+k->dut; //若通過始點p能增大終點x的ve則增大

k=k->next;

} }if(madjvex;

if(vl[p]>vl[x]-k->dut)

vl[p]=vl[x]-k->dut; //若通過終點k能減小始點p的vl則減小

k=k->next;

} }printf("critical pathes are as follows:\n");

for(int i=0;iadjvex;

if(ve[i]==vl[x]-k->dut)

printf("<%d,%d>\n",i+1,x+1);

k=k->next;

} }}

4.主函式如下:

int main()

拓撲排序,關鍵路徑

拓撲排序 對於乙個流程圖,可以用頂點表示活動,弧表示活動間的優先關係,這樣所表示的有向圖稱為頂點表示活動的網,即aov網。在網中,如果頂點i到頂點j有一條有向路徑,或者 i,j 是一條弧,則i是j的前驅,j是i的後繼。aov網中不應該出現環。拓撲排序的思想很簡單,1 在有向圖中選乙個沒有前驅的頂點輸...

拓撲排序 關鍵路徑

功能function description hdoj 2094 開發環境environment dev c 4.9.9.1 技術特點technique 版本version 作者author 可笑痴狂 日期date 20120812 備註notes 策略問題 一 本來想先用字典樹給名字編號,然後用建...

拓撲排序和關鍵路徑

拓撲排序 乙個無環的有向圖稱為無環圖 directed acyclic graph 簡稱dag圖。所有的工程或者某種流程都可以分為若干個小的工程或者階段,稱這些小的工程或階段為 活動 這些子程式之間存在一定的約束,其中某種子工程的開始必須在另一些子工程完成之後。因此dag圖表示乙個工程,其中有向邊表...