AOE網求關鍵路徑 c++代碼


題目:

給定10個結點以及結點間的權值,試着求解其任意兩點間的關鍵路徑。

分析:

AOE網原本是存在入點和出點的,這里求“任意節點”,所以會出現不存在的情況。(雖然我覺得這部分不是很必要…)

基本步驟參考了這篇,寫得非常好,一個例子遠比大段文字描述來得清晰明了。

由於上面那篇文章里的例子是9個點,而題目要求的是10個點,我在v1前面加了一個v0,對結果沒有什么影響。

代碼如下:

/*算法:
1.輸入邊數m;
2.初始化權重d[i][j]為max(0<=i<m,0<=j<m);
3.輸入每條邊的起點u終點v及其權重w,設置d[u][v]=w;
4.輸入要查詢的兩點first和last;
5.初始化的earliest[i]=0; latest[i]=max; path[i]=max(0<=i<10);
6.從k=first開始(earliest[first]=0),遞歸查找下一個節點i,然后計算各個點最早開始的時間earliest[i],如果earliest[k]+d[k][i]>earliest[i]則更新earliest[i];如果發現沒有任何節點i與k相連,則輸出“路徑不存在”;
7. 從k=last開始(latest[last]=earliest[last]),遞歸查找上一個節點i,然后計算各個點最晚開始的時間latest[i],如果latest[k]-d[i][k]<latest[i]則更新latest[i];
8. 從k=first開始,循環查找下一個節點i,如果latest[i]-d[k][i]==earliest[k],則k->i為關鍵路徑,把i加入到path中。
9.打印輸出path的內容
*/
#include<iostream>
using namespace std;
#define max 1000000
int d[10][10];
int earliest[10];
int latest[10];
int path[10];
void findEarliest(int k,int last);
void findLatest(int k,int first);
bool flag=false;//用於判斷是否存在關鍵路徑

int main(){
	int i,j,k,m,n=10;
	int u,v,w;
	int first,last,count=0;
	int next;
	cout<<"請輸入邊數:"; 
	cin>>m;

	for(i=0;i<m;i++){
		for(j=0;j<m;j++)
			d[i][j]=max;
	}
	cout<<"請輸入每條邊的頂點及其權重"<<endl;
	for(i=0;i<m;i++){
		cin>>u>>v>>w;
		d[u][v]=w;
	} 
	cout<<"請輸入要查詢的兩點:"; 
	cin>>first>>last;
	
	for(i=0;i<10;i++){
		earliest[i]=0;
		latest[i]=max;
		path[i]=max;
	}
	
	k=first;path[0]=k;count=1;
	findEarliest(k,last);
	if(!flag){
		cout<<"路徑不存在";
		return 0; 
	}
	
	k=last;latest[k]=earliest[k];
	findLatest(k,first);
	
	k=first;
	while(k!=last){
		for(i=0;i<10;i++){
			if(d[k][i]!=max&&(latest[i]-d[k][i]==earliest[k])){
				path[count++]=i;
				k=i;
				break;
			}
		}
	}
	cout<<"關鍵路徑為:"<<endl; 
	for(i=0;path[i]!=last;i++){
		cout<<path[i]<<"->";
	}
	cout<<path[i];

}

void findEarliest(int k,int last){
	if(k==last)
		return;
	flag=false;
	for(int i=0;i<10;i++){
		if(d[k][i]<max){
			flag=true;
			if((earliest[k]+d[k][i])>earliest[i])
				earliest[i]=earliest[k]+d[k][i];
			findEarliest(i,last);
		}
	}
        //如果flag沒有在循環中被修改為ture,則說明沒有節點與k相連(即沒有進入if語句內,函數返回不再進行遞歸),然后在主函數中判斷flag的值來決定是否繼續
}
void findLatest(int k,int first){
	if(k==first)
		return;
	for(int i=0;i<10;i++){
		if(d[i][k]<max){
			if(latest[k]-d[i][k]<latest[i])
				latest[i]=latest[k]-d[i][k];
			findLatest(i,first);
		}
	}
}

結果截圖:


反思:

采用遞歸和大量循環遍歷在時間上效率很低。本題只有十個點,如果數據規模較大,改成用指針查找或許比較快,但是數據結構的建立就比較麻煩了。

本文是個人學習記錄,如有錯誤請指出!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM