关键路径(CriticalPath)
我们把路径上各个活动所持续时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫做关键活动.。
AOV网和AOE网
在这里插入图片描述算法用到的4个关键变量:
- etv (Earliest time of vertex):事件的最早发生时间,即顶点k的最早发生时间
- ltv(Latest time of vertex):事件最晚发生时间,即顶点k的最晚发生时间
- ete(Earliest time of edge):活动最早开工时间,即弧k的最早发生时间
- lte(Latest time of edge):活动最晚开工时间,即弧k的最晚发生时间
我们可以根据1,2求得3,4,再根据ete[k] 是否与lte[k]相等来判断k是否为关键活动
etv[k] 与 ltv[k]的计算公式:
在这里插入图片描述 在这里插入图片描述关键路径算法借助到了改进过的拓扑排序算法,多了一个stack2栈,用来存放倒过来的拓扑序列(由于栈是后进先出的),同时计算生成了etv数组,计算公式如上图。
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define STATUS int
typedef struct EdgeNode
{
int adjvex;/*邻接点域*/
int weight;/*权值*/
struct EdgeNode *next;
}EdgeNode;
typedef struct VertexNode
{
int in; /*入度*/
int data;
EdgeNode *firstEdge;
}VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes, numEdges;
}*GraphAdjList, graphAdjList;
/*改进的辅助拓扑排序算法*/
/*需要定义几个全局变量*/
int *etc, *ltv;
int *stack2;/*stack2存放拓扑序列的栈*/
int top2; /* top2必须是全局变量,以为在辅助算法和主算法都用到了 */
Status TopologicalSort(GraphAdjList G)
{
EdgeNode *e;
int i, k, gettop;
int top = 0;
int count = 0;
int top2 = 0;/*初始化stack2数组的栈顶指针*/
int *stack;
stack = (int *)malloc(G->numVertexes * sizeof(int));
etv = (int *)malloc(G->numVertexes * sizeof(int));/*初始化*/
stack2 = (int *)malloc(G->numVertexes * sizeof(int));/*初始化*/
for(i = 0; i < G->numVertexes; i++)
{
etv[i] = 0;/*每个事件的最早发生时间,都先初始化为0*/
if(0 == G->adjList[i].in)
{
stack[++top] = i;/*如果入度为0,入栈*/
}
}
while(top != 0)
{
gettop = stack[top--];
count++;
stack2[++top2] = gettop;/*stack2栈用于保存拓扑序列,后进先出,所以是倒过来的*/
for(e = G->adjList[gettop].firstEdge; e; e = e->next)
{
k = e->adjvex;
if(!(--G->adjList[k].in))
{
stack[++top] = k;
}
if((etv[gettop] + e->weight) > etv[k])
{
/*gettop就是刚刚弹出的顶点,k就是与gettop相邻的顶点 找一个大的值保存*/
/*v[gettop] ----[weight]----> v[k]*/
/*确定顶点k事件的最早发生时间并且保存以供后续的关键路径算法使用。*/
etv[k] = etv[gettop] + e->weight;
}
}
}
if(count < G->numVertexes)
{
return ERROR;
}else
{
return OK;
}
}
void CriticalPath(GraphAdjList G)
{
EdgeNode *e;
int i, gettop, k, j;
int ete, lte;
TopologicalSort(G);
ltv = (int *)malloc(G->numVertexes * sizeof(int))
for(i = 0; i < G->numVertexes; i++)
{
ltv[i] = etv[G->numVertexes-1];/*所有事件的最晚发生时间都初始化为 拓扑序列最后一个顶点事件的最早发生时间*/
}
/*从后往前开始计算ltv,ltv的计算公式在图中给出*/
while(top2 != 0)
{
gettop = stack2[top2--];
for(e = G->adjList[gettop].firstedge; e; e = e->next)
{
k = e->adjvex;
if(ltv[k] - e->weight < ltv[gettop])
{
/* v[gettop] -----[weight]------> v[k] */
itv[gettop] = ltv[k] - e->weight;
}
}
}
for(j = 0; j < G->numVertexes; j++)
{
for(e = G->adjList[j].firstedge; e; e = e->next)
{
k = e->adjvex;
ete = etv[j]; /*活动最早开始时间就等于事件最早发生时间*/
lte = ltv[k] - e->weight; /*活动最晚开始时间等于 后继事件最晚发生时间 减去 活动的持续时间(权值)*/
if(ete == lte)
{
/*输出打印*/
printf("<v%d, v%d> length: %d, ", G->adjList[j].data, G->adjList[k].data, e->weight);
}
}
}
}
网友评论