一.先給出幾個概念:
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圖表示乙個工程,其中有向邊表...