【关键路径问题(Critical Path)——图】


AOE网(Activity On Edges)------用边表示活动的网络
1、用一个有向图表示一个工程的各子工程及其相互制约的关系,弧表示活动,权表示活动持续的时间,顶点表示事件(活动的开始或结束时间),称这种有向图为边表示活动的网,简称AOE网。
2、AOE网用来估算工程的完成时间。

一、基本术语

源点:入度为0的顶点(只有一个)
汇点:出度为0的顶点(只有一个)
路径长度:路径上各活动持续时间之和
整个工程完成的时间:从有向图的源点到汇点的最长路径
关键路径:路径长度最长的路径

在这里插入图片描述

在这里插入图片描述

二、如何求关键路径

1、问题分析

在这里插入图片描述

2、求关键路径的步骤

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、算法实现

1、算法思想

(1)设每个结点的最早发生时间为0,将入度为0的结点进栈
(2)将栈中入度为0的结点V取出,并压入另一个栈,用于形成逆向拓扑排序的序列
(3)根据邻接表找到结点V的所有的邻接结点,将结点V的最早发生时间+活动的权值 得到的和同邻接结点的原最早发生时间进行比较;如果该值大,则用该值取代原最早发生时间。另外,将这些邻接结点的入度减一。如果某一结点的入度变为0,则进栈。
(4)反复执行2、3;直至栈空为止。

2、算法描述

Status CriticalPath(ALGraph G)
{
	//G为邻接表存储的有向网,输出G的各项关键活动
	if (!TopologicalOrder(G, topo)) return ERROR;
	//调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环
	n = G.vexnum;			//n为顶点的个数
	for (i = 0;i < n;i++)			//给每个事件的最早发生时间置初值为0
		ve[i] = 0;
	/*按照拓扑次序求每个事件的最早发生时间*/
	for (i = 0;i < n;i++)			//for循环结束才能求得最早发生时间
	{
		k = topo[i];			//取得拓扑序列中的顶点序号k
		p = G.vertices[k].firstarc;			//p指向k的第一个邻接点
		while (p != NULL)			//依次更新k的所有邻接顶点的最早发生时间
		{
			j = p->adjvex;			//j为邻接顶点的序号
			if (ve[j] < ve[k] + p->weight)			//更新顶点j的最早发生时间ve[j]
				ve[j] = ve[k] + p->weight;
			p = p->nextarc;			//p指向k的下一个邻接顶点
		}
	}
	for (i = 0;i < n;i++)			//给每个事件的最迟发生时间置初值为ve[n-1]
		vl[i] = ve[n - 1];
	/*按逆拓扑次序求每个事件的最迟发生时间*/
	for (i = n - 1;i >= 0;i--)
	{
		k = topo[i];			//取得拓扑序列中的顶点序号k
		ArcNode* p = G.vertices[k].firstarc;			//p指向k的第一个邻接顶点
		while (p != NULL)
		{	//根据k的邻接点,更新k的最迟发生时间
			j = p->adjvex;			//j为邻接顶点的序号
			if (vl[k] > vl[j] - p->weight)			//更新顶点k的最迟发生时间vl[k]
				vl[k] = > vl[j] - p->weight;
			p = p->nextarc;			//p指向下一个邻接顶点
		}
	}
	/*判断每一活动是否为关键活动*/
	for (i = 0;i < n;i++)
	{ //每次循环针对vi为活动开始点的所有活动
		p = G.vertices[i].firstarc;			//p指向i的第一个邻接顶点
		while (p != NULL)
		{
			j = p->adjvex;			//j为i的邻接顶点的序号
			e = ve[i];			//计算活动<vi,vj>的最早开始时间
			l = vl[j] - p->weight;			//计算活动<vi,vj>的最迟开始时间
			if (e == l)		//若为关键活动,输出<vi,vj>
				cout << G.vertices[i].data << G.vertices[j].data;
			p = p->nextarc;			//p指向i的下一个邻接顶点
		}
	}
}
  • 64
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 136
    评论
关键路径算法是一种用于确定项目中关键任务和最短完成时间的方法。在Java中,可以使用论和拓扑排序的思想来实现关键路径算法。以下是一个简单的Java实现示例: ```java import java.util.*; public class CriticalPath { private int V; // 顶点数 private LinkedList<Integer>[] adj; // 邻接表 private int[] indegree; // 入度数组 private int[] earliest; // 最早开始时间数组 private int[] latest; // 最晚开始时间数组 public CriticalPath(int V) { this.V = V; adj = new LinkedList[V]; indegree = new int[V]; earliest = new int[V]; latest = new int[V]; for (int i = 0; i < V; i++) { adj[i] = new LinkedList<>(); } } public void addEdge(int u, int v) { adj[u].add(v); indegree[v]++; } public void findCriticalPath() { // 计算最早开始时间 calculateEarliest(); // 计算最晚开始时间 calculateLatest(); // 打印关键路径 printCriticalPath(); } private void calculateEarliest() { Queue<Integer> queue = new LinkedList<>(); for (int i = 0; i < V; i++) { if (indegree[i] == 0) { queue.add(i); earliest[i] = 0; } } while (!queue.isEmpty()) { int u = queue.poll(); for (int v : adj[u]) { indegree[v]--; if (indegree[v] == 0) { queue.add(v); } earliest[v] = Math.max(earliest[v], earliest[u] + 1); } } } private void calculateLatest() { int lastVertex = V - 1; latest[lastVertex] = earliest[lastVertex]; for (int u = lastVertex - 1; u >= 0; u--) { for (int v : adj[u]) { latest[u] = Math.min(latest[u], latest[v] - 1); } } } private void printCriticalPath() { System.out.println("关键路径为:"); for (int u = 0; u < V; u++) { for (int v : adj[u]) { if (earliest[u] == latest[u]) { System.out.println(u + " -> " + v); } } } } public static void main(String[] args) { int V = 6; // 顶点数 CriticalPath graph = new CriticalPath(V); // 添加边 graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 3); graph.addEdge(2, 3); graph.addEdge(2, 4); graph.addEdge(3, 5); graph.addEdge(4, 5); // 执行关键路径算法 graph.findCriticalPath(); } } ``` 这是一个简单的关键路径算法的Java实现示例。它使用邻接表来表示有向无环,并使用拓扑排序的思想计算最早开始时间和最晚开始时间。最后,根据最早开始时间和最晚开始时间的比较,找出关键路径并打印出来。
评论 136
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FEI..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值