关键路径介绍
AOE网:在一个表示工程的带权有向图中,用顶点表示事件(比如:发动机造好啦),用有向边表示活动(比如:我正在造发动机),用边上的权值表示活动的持续时间(比如:造发动机需要3天),这种有向图的边表示的活动的往,就是AOE网。
这个网有一个源点和一个汇点,源点到汇点的最长路径称作关键路径,关键路径上的活动称为关键活动。
关键路径算法原理
首先需要对拓扑排序进行改进,用于求出etv[]数组。
int *etv;
int top2;
int *stack2;
int TopologicalSortloth(GraphVerter G)
{
EdgeNode *e;
int i;
int top = 0;
int gettop;
int count = 0;
int *stack;
stack = (int *)malloc(G.numvertexes * sizeof(int));
for(i = 0; i < G.numvertexes; i++)
{
if(G.verter[i]->in == 0)
stack[++top] = i;
}
top2 = 0;
etv = (int *)malloc(G.numvertexes * sizeof(int));
for(i = 0; i < G.numvertexes; i++)
etv[i] = 0;
stack2 = (int *)malloc(G.numvertexes * sizeof(int));
while(top != 0)
{
gettop = stack[top--];
printf("%d",G.verter[gettop]->data);
count++;
stack2[++top2] = gettop;
for(e = G.verter[gettop]->firstedge; e ; e = e->next)
{
G.verter[e->adjvex]->in--;
if(G.verter[e->adjvex]->in == 0)
stack[++top] = e->adjvex;
if((etv[gettop]+e->weight) > etv[e->adjvex])
etv[e->adjvex] = etv[gettop]+e->weight;
}
}
if(count < G.numvertexes)
return 0;
else
return 1;
}
关键路径算法:
1 首先调用TopologicalSortloth(GraphVerter G)函数,得到etv[]数组,以及stack2栈。
2 初始化ltv[]数组,全部赋值为最后一个顶点的最早发生时间。
3 在top2不为0的情况下开始循环,后一个活动最晚开始时间减去它的权值weight,得到前一个活动的最晚开始时间(注意最后一个顶点是一定在关键路径上的,所以最早开始时间和最晚开始时间是必然相等的),都存在ltv[]数组里面。
4 开始对每一个顶点的邻接表进行访问,顶点表是邻接表的前继顶点所在地,前继顶点发生的时间在etv,后接顶点发生的时间点在ltv,后接顶点减去weight,可能会等于etv,如果相等,则这条边在关键路径上。
代码如下
void CriticalPath(GraphVerter G)
{
EdgeNode *e;
int i,gettop,k,j;
int ete,lte;
TopologicalSortloth(G);
ltv = (int *)malloc(G.numvertexes * sizeof(int));
for(i = 0; i < G.numvertexes; i++)
{
ltv[i] = etv[G.numvertexes - 1];
}
while(top2 != 0)
{
gettop = stack2[top2--];
for(e = G.verter[gettop]->firstedge; e ; e = e->next)
{
k = e->adjvex;
if(ltv[k] - e->weight < ltv[gettop])
ltv[gettop] = ltv[k] - e->weight;
}
}
for(j = 0; j < G.numvertexes; j++)
{
for(e = G.verter[j]->firstedge; e ; e = e->next)
{
k = e->adjvex;
ete = etv[j];
lte = ltv[k] - e->weight;
if(ete == lte)
printf("<%d,%d> length : %d",G.verter[j]->data,G.verter[k]->data,e->weight);
}
}
}