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>
示例:
所以:
//關鍵路徑,不是有向無環圖返回-1,否則返回關鍵路徑長度//拓撲序列stack<int> topOrder;//拓撲排序,順便求ve數組bool topologicalSort(){ queue<int> q; for (int i = 0; i < n; i++) { if (inDegree[i] == 0) { q.push(i); } } while (!q.empty()) { int u = q.front(); q.pop(); topOrder.push(u);//將u加入拓撲序列 for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].v;//u的i號后繼結點編號為v inDegree[v]--; if (inDegree[v] == 0) { q.push(v); } //用ve[u]來更新u的所有后繼結點v if (ve[u] + G[u][i].w > ve[v]) { ve[v] = ve[u] + G[u][i].w; } } } if (topOrder.size() == n)return true; else return false;}//關鍵路徑,不是有向無環圖返回-1,否則返回關鍵路徑長度int CriticalPath(){ memset(ve, 0, sizeof(ve));//ve數組初始化 if (topologicalSort() == false) { return -1;//不是有向無環圖,返回-1 } fill(vl, vl + n, ve[n - 1]);//vl數組初始化,初始值為匯點的ve值 //直接使用topOrder出棧即為逆拓撲序列,求解vl數組 while (!topOrder.empty()) { int u = topOrder.top();//棧頂元素為u topOrder.pop(); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].v;//u的后繼結點 //用u的所有后繼結點v的vl值來更新vl[u] if (vl[v] - G[u][i].w < vl[u]) { vl[u] = vl[v] - G[u][i].w; } } } //遍歷鄰接表的所有邊,計算活動的最早開始時間e和最遲開始時間l 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; //活動的最早開始時間e和最遲開始時間l int e = ve[u], l = vl[v] - w; //如果e==l,說明u->v是關鍵活動 if (e == l) { PRintf("%d->%d/n", u, v);//輸出關鍵活動 } } } return ve[n - 1];//返回關鍵路徑長度}/*若事先不知道匯點編號,可以取ve數組的最大值:int maxLength = 0;for(int i=0;i<n;i++){ if(ve[i]>maxLength) { maxLength = ve[i]; }}fill(vl,vl+n,maxLength);若有多條關鍵路徑,可以類比最短路徑中保存前驅結點的做法,新建一個鄰接表來保存所有的關鍵活動*/
新聞熱點
疑難解答