求关键路径(AOE)

来源:互联网 发布:js页面加载时执行函数 编辑:程序博客网 时间:2024/05/14 07:49

求AOE网络的关键路径并输出

假设数据输入时采用如下个格式进行输入:首先输入顶点的个数n和边数m,然后输入每条边,每条边的数据占一行,格式为:u v,表示从顶点u到顶点v的一条有向边。


样例输入:

9 11
0 1 6
0 2 4
0 3 5
1 4 1
2 4 5
3 5 2
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4


样例输出:

The critical activities are:
A2:0->2
A5:2->4
A8:4->7
A7:4->6
A10:6->8
A11:7->8


#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <map>#include <cmath>#include <iostream>#include <stdexcept>#include <cstddef>#include <algorithm>#include <vector>#include <numeric>#include <cctype>#define LL long long#define Endl endl#define INF 0x7fffffff//#define WJusing namespace std;const int maxn=100;const int maxm=200;struct ArcNode{int to,dur,no;struct ArcNode *next;};int n,m;ArcNode *List1[maxn];ArcNode *List2[maxn];int cont1[maxn],cont2[maxn],Ee[maxn];int Ei[maxn],e[maxm],L[maxm];void CriticalPath(){int i,j,k;int top1=-1;ArcNode *temp1;memset(Ee,0,sizeof(Ee));for(i=0;i<n;i++){if(cont1[i]==0){cont1[i]=top1; top1=i;}}for(i=0;i<n;i++){if(top1==-1){printf("Network has a cycle\n");return;}else{j=top1; top1=cont1[top1];temp1=List1[j];while(temp1!=NULL){k=temp1->to;if(--cont1[k]==0){cont1[k]=top1; top1=k;}if(Ee[j]+temp1->dur>Ee[k])Ee[k]=Ee[j]+temp1->dur;temp1=temp1->next;}}}int top2=-1;ArcNode *temp2;for(i=0;i<n;i++){Ei[i]=Ee[n-1];if(cont2[i]==0){cont2[i]=top2; top2=i;}}for(i=0;i<n;i++){j=top2; top2=cont2[top2];temp2=List2[j];while(temp2!=NULL){k=temp2->to;if(--cont2[k]==0){cont2[k]=top2; top2=k;}if(Ei[j]-temp2->dur<Ei[k])Ei[k]=Ei[j]-temp2->dur;temp2=temp2->next;}}memset(e,0,sizeof(e));memset(L,0,sizeof(L));printf("The critical activities are:\n");for(i=0;i<n;i++){temp1=List1[i];while(temp1!=NULL){j=temp1->to; k=temp1->no;e[k]=Ee[i]; L[k]=Ei[j]-temp1->dur;if(e[k]==L[k])printf("A%d:%d->%d\n",k,i,j);temp1=temp1->next;}}}int main(int argc, char *argv[]){#ifdef WJ//freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifint i,u,v,w;scanf("%d%d",&n,&m);memset(List1,0,sizeof(List1));memset(List2,0,sizeof(List2));memset(cont2,0,sizeof(cont2));memset(cont2,0,sizeof(cont2));ArcNode *temp1,*temp2;for(i=0;i<m;i++){scanf("%d%d%d",&u,&v,&w);cont1[v]++;temp1=new ArcNode;temp1->to=v; temp1->dur=w;temp1->no=i+1; temp1->next=NULL;if(List1[u]==NULL) List1[u]=temp1;else{temp1->next=List1[u];List1[u]=temp1;}cont2[u]++;temp2=new ArcNode;temp2->to=u; temp2->dur=w;temp2->no=i+1; temp2->next=NULL;if(List2[v]==NULL) List2[v]=temp2;else{temp2->next=List2[v];List2[v]=temp2;}}CriticalPath();for(i=0;i<n;i++){temp1=List1[i]; temp2=List2[i];while(temp1!=NULL){List1[i]=temp1->next;delete temp1;temp1=List1[i];}while(temp2!=NULL){List2[i]=temp2->next;delete temp2;temp2=List2[i];}}return 0;}



思路(计算关键路径的算法):

1、输入m条带权的有向边,建立邻接表结构;

2、从源点E0出发,令Ee[0]=0,按拓扑有序的顺序计算每个顶点的Ee[i],i=1,2,....,n-1;若拓扑排序的循环次数小于顶点数n,则说明网络中存在有向环,不能继续求关键路径。

3、从汇点En-1出发,令El[n-1]=Ee[n-1],按逆拓扑有序顺序求各顶点的El[i],i=n-2,n-3,....,0;

4、根据各顶点的Ee[i]和El[i],求各条有向边的e[k]和l[k];

5、对网络中的每条边,如果满足e[k]==l[k],则是关键活动;求出所有关键活动并输出。

0 0
原创粉丝点击