图-关键路径算法

关键路径(CriticalPath)

我们把路径上各个活动所持续时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫做关键活动.。

AOV网和AOE网

在这里插入图片描述

算法用到的4个关键变量:

  1. **etv (Earliest time of vertex):**事件的最早发生时间,即顶点k的最早发生时间
  2. **ltv(Latest time of vertex):**事件最晚发生时间,即顶点k的最晚发生时间
  3. **ete(Earliest time of edge):**活动最早开工时间,即弧k的最早发生时间
  4. **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);
			}
		}
	}
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值