首先AOE网络关于关键路径的求取是建立在拓扑排序得到的顺序上的,因为后面求early和late的顺序要求求后面时前面已知,如果我要求到数据结构的距离却发现到c语言的距离还不知道显然求不出来.
求出关键路径后分别求出early和late最后当early和late相等时就是关键路径,注意关键路径可能有几条比如1->2->4,1->3->4的长度一样则会输出1,2,3,4解决办法是判断从前一个节点到后一个是否可行,比如发现2->3没有路,自然不可行(假设2->3有路,必然有一个不是关键路径,如果前一个为真,那么加上一个路径权值怎么也不这个值大,不可能相等.
当然这样第一个节点要单独处理,因为他没有之前的节点。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
queue<int>q;
int s[100][100];
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
int n,m,i,j,a,b,c,count,temp,mount;
int indegree[100],ans[100],early[100],late[100];
memset(indegree,0,sizeof(indegree));
memset(ans,0,sizeof(ans));
memset(early,0,sizeof(early));
memset(s,0,sizeof(s));
scanf("%d%d",&n,&m);
count=0;
for (i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
s[a][b]=c;
indegree[b]++;
}
for (i=0;i<n;i++)
if (!indegree[i])
{
q.push(i);
ans[count++]=i;
}
while(!q.empty())
{
temp=q.front();
q.pop();
for (i=0;i<n;i++)
if (s[temp][i])
{
indegree[i]--;
if (!indegree[i])
{
q.push(i);
ans[count++]=i;
}
}
}
if (count<n)
{
printf("含有回路\n");
return 0;
}//此后count一律等于n
for (i=1;i<count;i++)
for (j=0;j<i;j++)
if (s[ans[j]][ans[i]])
early[ans[i]]=max(early[ans[i]],early[ans[j]]+s[ans[j]][ans[i]]);
for (i=0;i<n;i++)
late[i]=9999;
late[ans[n-1]]=early[ans[n-1]];
for (i=count-2;i>=0;i--)//dp求第ans[i]的late值即从j>i找ans[j]与ans[i]连同并且较小的那个
for (j=i+1;j<count;j++)
if (s[ans[i]][ans[j]])
late[ans[i]]=min(late[ans[i]],late[ans[j]]-s[ans[i]][ans[j]]);
for (i=0;i<n;i++)
printf("%d的最早发生时间为%d最晚发生时间为%d\n",ans[i],early[ans[i]],late[ans[i]]);
i=-1;
do
{
i++;
mount=i;
}while(late[ans[i]]!=late[ans[i]]);
printf("%d ",ans[i]);
for (i=1;i<n;i++)
if ((late[ans[i]]==early[ans[i]])&&(s[ans[mount]][ans[i]]))
{
mount=i;
printf("%d ",ans[i]);
}
printf("关键路径长为%d\n",late[ans[n-1]]);
return 0;
}