1、ve数组的求解
ve:顶点(事件)的最早开始时间(时刻)。
//拓扑序列
stack<int> topOrder;
//拓扑排序,顺便求ve数组
bool topologicalSort()
{
queue<int> q;
for(int i=0;i<n;i++) //遍历所有点,将入度为0的点加入队列
{
if(inDegree[i]==0)
{
q.push(i);
}
}
while(!q.empty()) //队列非空
{
int u=q.front();
q.pop();
topOrder.push(u);
for(int i=0;i<G[u].size();i++) //遍历u的所有后继节点
{
int v=G[u][i];
inDegree[v]--;
if(inDegree[v]==0)
{
q.push(v);
}
//更新ve数组
if(ve[u]+G[u][i].w>ve[v])
{
ve[v]=ve[u]+G[u][i];
}
}
}
if(topOrder.size()==n) return true;
else return false;
}
2、vl数组的求解
vl:顶点(事件)的最迟开始时间(时刻)。
fill(vl,vl+n,ve[n-1]);
while(!topOrder.empty()) //topOrder出栈即为逆拓扑排序
{
int u=topOrder.top();
topOrder.pop();
for(int i=0;i<G[u].size();i++) //遍历u的所有后继节点
{
int v=G[u][i].v;
if(vl[v]-G[u][i].w<vl[u])
{
vl[u]=vl[v]-G[u][i];
}
}
}
3、求解关键路径的长度
关键节点:
边(活动)的最早开始时间=最迟开始时间。
int criticalPath()
{
memset(ve,0,sizeof(ve));
if(topologicalSort()==false)
{
return -1;
}
//求解vl数组
fill(vl,vl+n,ve[n-1]);
while(!topOrder.empty())
{
int u=topOrder.top();
topOrder.pop();
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v;
if(vl[v]-G[u][i].w<vl[u])
{
vl[u]=vl[v]-G[u][i].w;
}
}
}
for(int u=0;u<n;u++) //遍历邻接表的所有边
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
int w=G[u][i].w;
int e=ve[u]; //活动的最早开始时间
int l=vl[v]-w; //活动的最迟开始时间
if(e==l)
{
printf("%d->%d\n",u,v);
}
}
}
return ve[n-1]; //返回关键路径的长度
}

本文介绍了如何求解有向无环图(DAG)中的关键路径,包括ve数组和vl数组的求解过程,ve表示顶点的最早开始时间,vl表示顶点的最迟开始时间。当边的最早开始时间等于最迟开始时间时,该边位于关键路径上。通过这样的分析,可以确定关键路径的长度。

1573

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



