关键路径求解要用到拓扑排序,先从头往后拓扑,在ve[i]中记录每个事件的最早发生时间。
然后把ve[]的值赋给vl[],从后边向前求每个事件的最迟发生时间,记录在vl[]中。
如果ve[]中的值和vl[]中的值对应相等,则这个事件在关键路径上。
假设初始AOE网是这样的:

关键路径:

代码:
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
int map[101][101];
int indegree[101];
int indegreeCopy[101];
int n,m;
int ve[101];//事件V的最早发生时间
int vl[101];//事件V的最迟发生时间
bool criticalPath()
{
//forward
ve[1]=0;
queue<int> Q;
stack<int>S;
int nodeCount=0;
for(int i=1; i<=n; i++)
{
if(!indegree[i])
{
Q.push(i);//入度为0的顶点进队
}
}
nodeCount=0;
while(!Q.empty())
{
int k=Q.front();
S.push(k);
Q.pop();
//cout<<k<<" ";
for(int i=1; i<=n; i++)
{
if(map[k][i]>0 && ve[i]<ve[k]+map[k][i])
{
ve[i]=ve[k]+map[k][i];
}
}
nodeCount++;
for(int j=1; j<=n; j++)
{
if(map[k][j]!=-1)
{
indegree[j]--;
if(!indegree[j])
{
Q.push(j);
}
}
}
}
if(nodeCount<n)
{
cout<<"There is cycle on the graph.\n";
return false;
}
//backward
for(int i=1; i<=n; i++)
{
vl[i]=ve[i];
}
while(!S.empty())
{
int k=S.top();
S.pop();
//cout<<k<<" ";
//注意是矩阵的转置
//对起点不处理
for(int i=2; i<=n; i++)
{
if(map[i][k]>0 && vl[i]<vl[k]-map[i][k])
{
vl[i]=vl[k]-map[i][k];
}
}
}
return true;
}
int main()
{
/*
input test
9 11
1 2 6
1 3 4
2 5 1
3 5 1
5 7 9
5 8 7
7 9 2
8 9 4
1 4 5
4 6 2
6 8 4
*/
freopen("in.txt","r",stdin);
memset(map,-1,sizeof(map));
int a,b,c;
scanf("%d %d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d %d %d",&a,&b,&c);
map[a][b]=c;
indegree[b]++;
indegreeCopy[b]++;
}
criticalPath();
cout<<"事件的最早发生时间:"<<endl;
for(int i=1; i<=n; i++)
{
cout<<ve[i]<<" ";
}
cout<<endl<<endl;
cout<<"事件的最晚发生时间:"<<endl;
for(int i=1; i<=n; i++)
{
cout<<vl[i]<<" ";
}
cout<<endl<<endl;
// output the answer
int ans[n];
bool visited[n];
memset(visited,1,sizeof(visited));
int p=0;
for(int i=1; i<=n; i++)
{
if(ve[i]==vl[i])
{
//cout<<i<<" ";
ans[p++]=i;
visited[i]=0;
}
}
cout<<endl<<"关键路径上的事件:"<<endl;
for(int k=0; k<p; k++)
cout<<ans[k]<<" ";
cout<<endl;
cout<<endl<<"关键活动:"<<endl;
int flag=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(map[i][j]!=-1)
{
for(int k=0; k<p; k++)
{
if(i==ans[k] || j==ans[k])
{
flag++;
}
}
if(flag==2)
{
cout<<i<<" -> "<<j<<endl;
}
flag=0;
}
}
}
return 0;
}
结果:

本文介绍了关键路径求解算法,该算法利用拓扑排序来确定每个事件的最早和最迟发生时间。通过比较ve[]和vl[]数组中的值,可以找出位于关键路径上的事件。文章还提供了一段代码示例和相应的结果。
3673

被折叠的 条评论
为什么被折叠?



