問題與解答
問題描述
計算AOE-網中關鍵路徑的長度。
輸入格式
輸入數據第一行是一個正整數,表示圖中的頂點個數n(頂點將分別按0,1,…,n-1進行編號),頂點數不超過100,其中0為源點,n-1為匯點。之后的n行每行都包含n個整數,為AOE-網的鄰接矩陣,其中0表示兩個頂點間無直接可達的弧,大於0的整數表示活動持續的時間。
輸出格式
輸出AOE-網中關鍵路徑的長度,如果網中有環,則輸出“NO”。
樣例輸入
9
0 6 4 5 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 2 0 0 0
0 0 0 0 0 0 9 7 0
0 0 0 0 0 0 0 4 0
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 0
樣例輸出
18
輸出說明:
如果網中有環,則示例輸出如下:NO
//求解關鍵路徑長度
//只需要求關鍵路徑長度,不需要打印關鍵路徑
//所以只需要在TopoSort()上進行改進即可
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
#define MaxN 100 //最大頂點數
int n; //頂點數
int G[MaxN][MaxN]; //鄰接矩陣保存圖
int InDegree[MaxN] = {0}, Ve[MaxN]; //入度矩陣
//Ve數組:事件最早開始時間,初始化為0
int TopoSort(); //拓撲排序
int main(){
int i,j,w;
scanf("%d",&n);
for(i = 0; i < n; i++){ //讀入鄰接矩陣
for(j = 0; j < n; j++){
scanf("%d",&w);
G[i][j] = w;
if(w) InDegree[j]++; //j頂點入度+1
}
}
int Path_Length = TopoSort();
if(Path_Length == -1) printf("No");
else printf("%d", Path_Length);
}
int TopoSort(){ //改動后的拓撲排序,返回關鍵路徑長度
fill(Ve,Ve+n,0); //初始化Ve數組
queue<int> q;
int i,node;
for(i = 0; i < n; i++){
if(InDegree[i] == 0)
q.push(i);
}
while(!q.empty()){
int u = q.front();
q.pop();
for(i = 0; i < n; i++){
if(G[u][i] != 0){
InDegree[i]--;
if(InDegree[i] == 0)
q.push(i);
//更新Ve數組:在原TopoSort()基礎上添加的部分
if(Ve[u] + G[u][i] > Ve[i])
Ve[i] = Ve[u]+G[u][i];
}
}
node++;
}
if(node !=n) return -1; //存在有向環,拓撲排序失敗
else return Ve[n-1]; //拓撲排序成功,返回關鍵路徑長度
}
題后反思
- 本題只需要求解關鍵路徑的長度而不需要確定關鍵路徑的具體節點,所以只需要建立Ve數組即可,不需要用逆拓撲排序建立Vl求e與l。
- 注意點:實現時默認存在源點與匯點,匯點為 n-1 號頂點(從0開始計)。
- 關鍵路徑完整算法