C語言實現「關鍵路徑」的求解

2021-07-15 09:27:23 字數 3575 閱讀 2374

儘管是用c++編譯的,但程式中沒有應用什麼c++特性,應該算是c語言編寫吧。

一、概述

工程上常常用乙個有向無環圖來代表乙個專案(如下圖)。

以節點表示某個事件,以邊表示活動,邊上的數字表示活動的持續時間。在工程分析上,常常需要找到一條「關鍵路徑」,即此路徑直接決定專案的持續時間。

二、演算法描述

為求出關鍵路徑,首先要明確以下幾個概念:

c1.節點的最早可能開始時間ev

c2.節點的最遲允許開始時間lv

c3.活動(即邊)的最早可能開始時間ee

c4.活動的最遲允許開始時間le

c1: ev比較容易理解,設起點的最早開始時間為0,下乙個節點的ev就是上乙個節點的ev加上邊的持續時間;若存在多條路徑到達同一節點的情況,則取最大值為該點的ev(因為只有前面所有活動全部完成後該點才能啟動)

c2: lv則要採用倒推的方式,如果已知終點的ev為t,則與終點直接相連節點的lv=t-邊的持續時間;如果存在多條路徑,ev取最小值。

c3: 邊的ee等於其起點的ev

c4:邊的le等於其終點的lv減去邊的持續時間

演算法書上指出:對於圖中某條邊,如果滿足 ev=lv,則此邊為關鍵路徑(的組成部分) 

三、演算法實現

3.1輸入描述

第一行輸入圖的頂點個數n 和邊數m,

第二行開始是邊的資訊,每條邊的資料佔一行,格式為:s e t(即表示從頂點s 到頂點e 的一條權值為t的邊)頂點編號從0開始!(為了程式設計方便)

對於上面的圖,可以寫為:

9 11

0 1 6

0 2 4

0 3 5

1 4 1

2 4 1

3 5 2

4 6 9

4 7 7

5 7 4

6 8 2

7 8 4

3.2 輸出描述

the critical path:

a1:0->1

a4:1->4

a8:4->7

a7:4->6

a10:6->8

a11:7->8

其中,an中n表示邊的編號,對應於輸入的順序

3.3 程式實現

/*

資料輸入時採用如下的格式:

首先輸入頂點個數n 和邊數m,

然後輸入每條邊,每條邊的資料佔一行,格式為:s e t;表示從頂點s 到頂點e 的一條權值為t的邊

頂點編號從0開始!(為了程式設計方便)

2016.7.22 by pospro

詳見:*/#include #include #define maxn 100 //the max num of vertex

#define maxm 200 //the max num of edges

using namespace std;

struct arcnode //儲存邊的資訊

;//全域性變數!

int n,m; //the number of vertex and edge,

arcnode* outedge[maxn]; //記錄每個頂點對應的出邊表

arcnode* inedge[maxn]; //記錄每個頂點對應的入邊表

int outord[maxn]; //每個頂點的出度

int inord[maxn]; //每個頂點的入度

int ev[maxn]; //earliest start time for vertex

int lv[maxn]; //latest start time for vertex

int ee[maxm]; //maxm!! earliest start time for edge

int le[maxm]; //latest start time for edge!!

void criticalpath()

//其它的都是套路(實現拓撲排序的套路),下面這兩句才是為求關鍵路徑而生的

//如果到達該點有多個路徑,最早開始時間必然是個值中的最大值!(因為有一條路徑未完成,該點就不能啟動)

//第乙個起點的ev值,在初始化時就被設為0了

if(ev[nxt]dur+ev[tmp])

ev[nxt]=tpnode->dur+ev[tmp];

tpnode=tpnode->next;}}

}//以入度鄰接表,再來一遍

int maxtime=0;

for(i=0;imaxtime)

maxtime=ev[i];

top=-1; //重新設棧頂

for(i=0; ito; //其實是找上乙個點

outord[nxt]--;

if(0==outord[nxt])

//下面兩句計算最遲開始時間

//只要有一條路徑決定它在更早的時間開始,就得更早開始,所以取各路徑最小值

if(lv[nxt]>(lv[tmp]-tpnode->dur))

lv[nxt]=(lv[tmp]-tpnode->dur);

tpnode=tpnode->next;}}

}//上面計算的都是節點(!)的最早和最遲開始時間,下面需要計算邊的

//若邊(活動)的最早開始==最遲開始時間,則該邊為關鍵路徑

printf("the critical path:\n");

for(i=0; ino; //tmp此時儲存邊的編號!!

nxt=tpnode->to;

ee[tmp]=ev[i];//邊的最早開始時間就是其起點的最早開始時間

le[tmp]=lv[nxt]-tpnode->dur; //邊的最遲開始時間,是其終點的最遲開始時間減去邊的持續時間

if(ee[tmp]==le[tmp])

printf("a%d:%d->%d\n",tmp,i,nxt);

tpnode=tpnode->next;}}

}int main()

//構建入邊表

inord[e]++;

newnode=new arcnode; // 必須重新賦值

newnode->to=s;

newnode->no=i+1;

newnode->dur=t;

newnode->next=null;

if(inedge[e]==null)

inedge[e]=newnode;

else

}//一次性獲得全部輸入後,執行程式的核心部分——找出關鍵路徑

criticalpath();

//release the memory

for(i=0;inext; //newnode不是新節點,只是借用一下其名字

delete outedge[i];

outedge[i]=newnode;

}while(inedge[i]!=null)

}return 0;

}

關鍵路徑 C語言實現

include include define maxvertexnum 50 define false 0 define true 1 typedef int bool typedef int vertex typedef int weighttype struct vertexnode 頂點結構 ...

關鍵路徑 C語言簡單實現

本文參考自 大話資料結構 對關鍵路徑的理解參考自 在乙個表示工程的帶權有向圖中,用頂點表示事件,用有向邊表示活動,用邊上的權值表示活動的持續時間,這種有向圖的邊表示活動的網,我們稱之為aoe網。我們把aoe網中沒有入邊的頂點稱為始點或源點,沒有出邊的頂點稱為終點或匯點。儘管aoe網和aov網都是用來...

用遺傳演算法求解迷宮路徑問題(c語言實現)

include include include include include include include include using namespace std define maph 100 高 define mapw 100 寬 define playersnumber 10000 每代個...