一、拓撲排序
設g=是乙個具有n個頂點的有向圖,v中的頂點序列v1,v2,v3,...,vn稱為乙個拓撲序列。若是圖中的一條邊或者從頂點vi到頂點vj有路徑,則在該序列中頂點vi必須排在頂點vj之前。
在乙個有向圖中找乙個拓撲序列的過程稱為拓撲排序。
用頂點表示活動,用有向邊表示活動之間的優先關係的有向圖稱為頂點表示活動的網。
拓撲排序方法如下:
1、從有向圖中選擇乙個沒有前驅(即入度為0)的頂點並且輸出它。
2、從圖中刪去該頂點,並且刪去從該頂點發出的全部有向邊。
3、重複上述兩步,直到剩餘的圖中不再存在沒有前驅的頂點為止。
這樣的操作結果有兩種:一種是圖中全部頂點都被輸出,即該圖中所有頂點都在其拓撲序列中,這說明圖中不存在迴路;另一種是圖中頂點未被全部輸出,這說明圖中存在迴路。所以可以通過對乙個有向圖進行拓撲排序,看是否產生全部頂點的拓撲序列來確定該圖中是否存在迴路。
二、aoe網與關鍵路徑
有向無環圖描述工程的預計進度,以頂點表示事件,有向邊表示活動,邊e的權c(e)表示完成活動e所需的時間,或者說活動e持續時間。圖中入度為0的頂點表示工程的開始事件,出度為0的頂點表示工程結束事件,稱這樣的有向圖為邊表示活動的網(aoe網)。
通常每個工程都只有乙個開始事件和乙個結束事件,因此表示工程的aoe網都只有乙個入度為0的頂點,稱為源點,和乙個出度為0的頂點,稱為匯點。如果圖中存在多個入度為0的頂點,只要加乙個虛擬源點,使這個虛擬源點到原來所有入度為0的點都有一條長度為0的邊,從而變成只有乙個源點。對存在多個出度為0的頂點的情況做類似的處理。只討論單源點和單匯點的情況。
利用這樣的aoe網能夠計算完成整個工程預計需要多少時間,並找出影響工程進度的「關鍵活動」,從而為決策者提供修改各活動的預計進度的依據。
在aoe網中,從源點到匯點的所有路徑中具有最大路徑長度的路徑稱為關鍵路徑。完成整個工程的最短時間就是aoe網中關鍵路徑的長度,或者說是aoe網中一條關鍵路徑上各活動持續時間的總和,把關鍵路徑上的活動稱為關鍵活動。關鍵活動不存在富餘的時間,而非關鍵活動可能存在富餘的時間。通常乙個aoe網可能存在多條關鍵路徑,但它們的長度是相同的。
因此,只要找出aoe網中的所有關鍵活動也就找到了全部的關鍵路徑。
/*** 實驗題目:
* 求aoe網中的所有關鍵活動
* 實驗目的:
* 領會拓撲排序和aoe網中關鍵路徑的求解過程及其演算法設計
* 實驗內容:
* 設計程式,求如下圖8.45所示的aoe網的所有關鍵活動
#define inf 32767 //定義∞
#define maxv 100 //最大頂點個數
typedef char infotype;
/*-------------------------以下定義鄰接矩陣型別---------------------------*/
typedef struct
vertextype; //頂點型別
typedef struct
matgraph; //完整的圖鄰接矩陣型別
//鄰接表表示法-將每個頂點的鄰接點串成乙個單鏈表
/*-----------以下定義鄰接表型別--------------*/
typedef struct arcnode
arcnode; //邊結點型別
typedef struct vnode
vnode; //鄰接表結點型別
typedef struct
adjgraph; //完整的圖鄰接表型別
/*-------------------------鄰接矩陣的基本運算演算法---------------------------*/
/*------------由邊陣列a、頂點數n和邊數e建立圖的鄰接矩陣g--------------------*/
void createmat(matgraph &g, int a[maxv][maxv], int n, int e)
/*------------輸出鄰接矩陣g--------------------*/
void dispmat(matgraph g)
printf("\n");}}
/*-------------------------鄰接表的基本運算演算法---------------------------*/
/*-------------------由邊陣列a、頂點數n和邊數e建立圖的鄰接表g--------------------*/
void createadj(adjgraph *&g, int a[maxv][maxv], int n, int e)
for(i = 0; i < n; i++) //檢查鄰接矩陣中的每個元素}}
g->n = n;
g->e = e;
}/*-------------------輸出鄰接表g--------------------*/
void dispadj(adjgraph *g)
printf("∧\n");}}
/*-------------------銷毀圖的鄰接表g--------------------*/
void destroyadj(adjgraph *&g)
free(pre);}}
free(g); //釋放頭結點陣列
}typedef struct keynodekeynode; // 關鍵活動型別
/*---------------------由含有n個頂點的有向圖g產生乙個拓撲序列--------------------*/
static bool topsort(adjgraph *g, int topseq)
}for(i = 0; i < g->n; i++)
}while(top > -1)
p = p->nextarc; // 找下乙個鄰接點}}
if(n < g->n)
return false; // 拓撲序列中不含所有頂點時
else
printf("\n");
return true;}}
/*---------------------從圖鄰接表g中求出從源點inode到匯點enode的關鍵活動[0...d]----------------------*/
static bool keypath(adjgraph *g, int &inode, int &enode, keynode keynode, int &d) // 引用型別
}for(i = 0; i < g->n; i++) // 先將所有事件的vl值置為最大值
vl[i] = ve[enode];
for(i = g->n - 2; i >= 0; i--)
}d = -1; // d存放keynode中的關鍵活動下標,置初值為-1
for(i = 0; i < g->n; i++)
p = p->nextarc;}}
return true;
}/*---------------------輸出圖g的關鍵活動----------------------*/
static void dispkeynode(adjgraph *g)
else
printf("不能求關鍵活動\n");
}int main(void)
/*a*/,/*b*/,
/*c*/, /*d*/,
/*e*/, /*f*/,
/*g*/, /*h*/,
/*i*/
};printf("建立圖的鄰接表:\n");
createadj(g, a, n, e);
printf("圖g的鄰接表:\n");
dispadj(g);
dispkeynode(g); // 求構成關鍵路徑的關鍵活動
destroyadj(g);
return 0;
}測試結果:
建立圖的鄰接表:
圖g的鄰接表:
頂點0: 1[6]-> 2[4]-> 3[5]->∧
頂點1: 4[1]->∧
頂點2: 4[1]->∧
頂點3: 7[2]->∧
頂點4: 5[9]-> 6[7]->∧
頂點5: 8[2]->∧
頂點6: 8[4]->∧
頂點7: 8[4]->∧
頂點8: ∧
拓撲序列:a d h c b e g f i
從源點a到匯點i的關鍵活動:(a,b) (b,e) (e,f) (e,g) (f,i) (g,i)
AOE網求關鍵路徑(關鍵活動)
aoe網求關鍵路徑 關鍵活動 aoe網求解關鍵路徑,所需的是有向無環圖 利用拓撲排序,如果序列長度為頂點數,則是無環,小於頂點數則是有環圖,有環圖是不滿足求aoe網的 注意的是,只有乙個源點,有乙個匯頂點,然後關鍵路徑不一定只有一條。注意,這裡要理解 頂點 事件 邊 活動 還有四個陣列下面有介紹 這...
求關鍵路徑 邊活動網(AOE)
題目大意 前提 有向無環圖 dag 才有解。aoe網 邊活動網 點為事件,帶權的邊集為活動,權為完成活動所需要的時間。求計算完成總事件的最短時間。即求最長路徑 此處最長即完成所有關鍵活動,即滿足了實現總事件的最短時間問題。思路 先求點,再求邊。求最長路徑 求所有關鍵活動 判斷是否為關鍵活動 最遲開始...
AOE網列印所有的關鍵路徑
思路是因為aoe網的關鍵路徑就是起點到終點的最長路徑 起點是入度為0的點,終點是出度為0的點 於是先用spfa求出起點到終點的最長距離,然後再用dfs求起點到終點的最長距離的路徑結果保留在ans陣列.include include include include includeusing names...