AOE網:在一個表示工程的帶權有向圖中,用頂點表示事件,用有向邊表示活動,邊上的權值表示活動的期間,稱這樣的有向圖叫做邊表示活動的網,簡稱AOE網。AOE網中沒有入邊的頂點稱為始點(或源點),沒有出邊的頂點稱為終點(或匯點)。
AOE網的性質:
⑴ 只有在某頂點所代表的事件發生後,從該頂點出發的各活動才能開始;
⑵ 只有在進入某頂點的各活動都結束,該頂點所代表的事件才能發生。
關鍵路徑:在AOE網中,從始點到終點具有最大路徑長度(該路徑上的各個活動所持續的時間之和)的路徑稱為關鍵路徑。
關鍵活動:關鍵路徑上的活動稱為關鍵活動。關鍵活動:e[i]=l[i]的活動
由於AOE網中的某些活動能夠同時進行,故完成整個工程所必須花費的時間應該為始點到終點的最大路徑長度。關鍵路徑長度是整個工程所需的最短工期。
與關鍵活動有關的量:
⑴ 事件的最早發生時間ve[k]
ve[k]是指從始點開始到頂點vk的最大路徑長度。這個長度決定了所有從頂點vk發出的活動能夠開工的最早時間。
⑵ 事件的最遲發生時間vl[k]
vl[k]是指在不延遲整個工期的前提下,事件vk允許的最晚發生時間。
⑶ 活動的最早開始時間e[i]
若活動ai是由弧<vk , vj>表示,則活動ai的最早開始時間應等於事件vk的最早發生時間。因此,有:e[i]=ve[k]
⑷ 活動的最晚開始時間l[i]
活動ai的最晚開始時間是指,在不延遲整個工期的前提下, ai必須開始的最晚時間。若ai由弧<vk,vj>表示,則ai的最晚開始時間要保證事件vj的最遲發生時間不拖後。因此,有:l[i]=vl[j]-len<vk, vj>
樣本:
所以:
具體的實現代碼如下:
#include<cstdio>#include<vector>#include<queue>#include<stack>#include<algorithm>using namespace std;const int maxn = 1000;int n;int ve[maxn], vl[maxn];struct Node{int v, w;}node;int inDegree[maxn] = { 0 };stack<int> topOrder;vector<Node> G[maxn];vector<int> pre[maxn];bool topologicalSort(){queue<int> q;int c = 0;for (int i = 0; i < n; i++){if (inDegree[i] == 0)q.push(i);}while (!q.empty()){int u = q.front(); c++;topOrder.push(u);q.pop();for (int i = 0; i < G[u].size(); i++){int v = G[u][i].v, w = G[u][i].w;inDegree[v]--;if (inDegree[v] == 0)q.push(v);if (ve[u] + w > ve[v])ve[v] = ve[u] + w;}}return c == n ? true : false;}vector<int> path;void DFS(int s, int e){if (s == e){path.push_back(s);for (int i = path.size() - 1; i >= 0; i--){printf("%d", path[i]);if (i > 0)printf("->");else printf("\n");}path.pop_back();return;}path.push_back(e);for (int i = 0; i < pre[e].size(); i++){DFS(s, pre[e][i]);}path.pop_back();}int criticalPath(){fill(ve, ve + n, 0);if (!topologicalSort()){return -1;}fill(vl, vl + n, ve[n - 1]);while (!topOrder.empty()){int u = topOrder.top();topOrder.pop();for (int i = 0; i < G[u].size(); i++){int v = G[u][i].v, w = G[u][i].w;if (vl[v] - w < vl[u]){vl[u] = vl[v] - w;}}}printf("所有的關鍵活動如下所示:\n");for (int u = 0; u < n; u++){for (int i = 0; i < G[u].size(); i++){int v = G[u][i].v, w = G[u][i].w;int e = ve[u], l = vl[v] - w;if (e == l){printf("%d->%d\n", u + 1, v + 1);//輸出時加1以還原輸入時做出的改變pre[v + 1].push_back(u + 1);}}}printf("所有的關鍵路徑如下所示:\n");DFS(1, n);return ve[n - 1];}int main(){freopen("i.txt", "r", stdin);//鍵盤輸入資料流重新導向為i.txt檔案輸入資料流int m;scanf("%d %d", &n,&m);//n為點數,m為邊數int a, b, w;for (int i = 0; i < m; i++){scanf("%d%d%d", &a, &b, &w);//a、b為事件,w為ab這條邊所表示的活動耗費的時間node.v = b-1; node.w = w;G[a-1].push_back(node);//實際儲存時為了方便a、b都減1}printf("關鍵路徑長度為:%d\n",criticalPath());return 0;}/*輸入為(即i.txt內容):9 111 2 61 3 41 4 52 5 13 5 14 6 25 7 95 8 76 8 47 9 28 9 4*/