利用有向网的的邻接表存储结构实现关键路径算法

时间: 2023-08-06 21:07:08 浏览: 49
关键路径算法是一种常用的项目管理工具,可以帮助确定项目中最长的关键路径和关键活动。实现关键路径算法需要用到有向网的邻接表存储结构,具体步骤如下: 1. 定义有向网的邻接表存储结构,其中包含顶点表和边表两个部分。 2. 根据项目的具体情况,构建有向网的邻接表,包括顶点和边的信息。 3. 对有向网进行拓扑排序,得到所有顶点的拓扑序列。 4. 对拓扑序列中的每一个顶点,分别计算其最早开始时间和最晚开始时间,并记录其前驱和后继活动。 5. 根据前面的计算结果,计算每一个活动的最早开始时间和最晚开始时间,以及其总时差。 6. 找到所有关键活动,即总时差为0的活动,以及关键路径,即所有关键活动构成的路径。 7. 输出关键路径和关键活动的信息。 需要注意的是,实现关键路径算法需要对有向网进行拓扑排序,因此有向网必须是一个有向无环图。如果有向网中存在环路,则无法进行拓扑排序,也无法求解关键路径和关键活动。
相关问题

采用邻接表存储,实现关键路径算法代码和思路

关键路径算法是用于求解工程项目中最长的完成时间和关键活动的一种算法。邻接表是一种图的存储方式,可以用来存储有向无环图(DAG),因此可以使用邻接表存储有向无环图来实现关键路径算法。 邻接表的基本思想是将图中每个点的出边存储到一个链表中,每个链表节点存储一个有向边的信息,包括该边的终点和权值。对于有向无环图中的每个节点,我们可以维护两个数组,一个存储该节点的入度,另一个存储该节点的最早开始时间。通过遍历整个图,我们可以计算出每个节点的最早开始时间和最晚开始时间,从而得到关键路径。 下面是使用邻接表存储有向无环图的伪代码: ``` struct EdgeNode { int to; // 有向边的终点 int weight; // 有向边权值 int next; // 指向下一个节点的指针 }; EdgeNode edge[MAX_EDGE_NUM]; // 存储所有的有向边 int head[MAX_NODE_NUM]; // 存储每个节点的第一条出边的位置 int inDegree[MAX_NODE_NUM]; // 存储每个节点的入度 int earliestTime[MAX_NODE_NUM]; // 存储每个节点的最早开始时间 int latestTime[MAX_NODE_NUM]; // 存储每个节点的最晚开始时间 void addEdge(int from, int to, int weight) { edge[edgeCnt].to = to; edge[edgeCnt].weight = weight; edge[edgeCnt].next = head[from]; head[from] = edgeCnt++; } void topologicalSort() { queue<int> q; for (int i = 1; i <= n; i++) { if (inDegree[i] == 0) { q.push(i); // 将所有入度为0的节点加入队列 earliestTime[i] = 0; // 起点的最早开始时间为0 } } while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; int w = edge[i].weight; inDegree[v]--; earliestTime[v] = max(earliestTime[v], earliestTime[u] + w); if (inDegree[v] == 0) { q.push(v); } } } } void calcLatestTime() { latestTime[n] = earliestTime[n]; // 终点的最晚开始时间等于最早开始时间 for (int u = n - 1; u >= 1; u--) { for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; int w = edge[i].weight; latestTime[u] = min(latestTime[u], latestTime[v] - w); } } } void printCriticalPath() { for (int i = 1; i <= n; i++) { if (earliestTime[i] == latestTime[i]) { // 找到关键路径上的节点 printf("%d ", i); } } printf("\n"); } int main() { memset(head, -1, sizeof(head)); memset(inDegree, 0, sizeof(inDegree)); memset(earliestTime, 0, sizeof(earliestTime)); memset(latestTime, INT_MAX, sizeof(latestTime)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w); // 添加一条有向边 inDegree[v]++; // 统计每个节点的入度 } topologicalSort(); // 计算每个节点的最早开始时间 calcLatestTime(); // 计算每个节点的最晚开始时间 printCriticalPath(); // 输出关键路径上的节点 return 0; } ``` 这段代码首先使用邻接表存储了所有的有向边,然后统计了每个节点的入度。接着使用拓扑排序的方法计算了每个节点的最早开始时间,最后计算了每个节点的最晚开始时间,并输出了关键路径上的节点。 需要注意的是,在计算每个节点的最晚开始时间时,需要从终点开始向起点遍历,因为只有先计算出终点的最晚开始时间,才能够计算出其他节点的最晚开始时间。

采用邻接表存储,实现关键路径算法具体代码

关键路径算法是一种用于确定项目完成所需时间的技术,其重点在于找出各个活动的最早开始时间、最晚开始时间、总时差和自由时差。在实现时采用邻接表存储有向无环图(DAG),具体代码如下: ```python from collections import defaultdict class Graph: def __init__(self, vertices): self.graph = defaultdict(list) self.vertices = vertices self.indegree = [0] * vertices self.topo_order = [] self.start_time = [0] * vertices self.end_time = [0] * vertices self.critical_path = [] def add_edge(self, u, v, weight): self.graph[u].append((v, weight)) self.indegree[v] += 1 def get_indegree(self, v): return self.indegree[v] def get_topo_order(self): return self.topo_order def get_start_time(self, v): return self.start_time[v] def get_end_time(self, v): return self.end_time[v] def get_critical_path(self): return self.critical_path def topological_sort(self): queue = [] for i in range(self.vertices): if self.indegree[i] == 0: queue.append(i) while queue: u = queue.pop(0) self.topo_order.append(u) for v, weight in self.graph[u]: self.indegree[v] -= 1 if self.indegree[v] == 0: queue.append(v) self.start_time[v] = max(self.start_time[v], self.end_time[u]) self.end_time[u] = max(self.end_time[u], self.start_time[u] + weight) def find_critical_path(self): for u in range(self.vertices): for v, weight in self.graph[u]: if self.start_time[u] + weight == self.start_time[v]: self.critical_path.append((u, v, weight)) if __name__ == '__main__': g = Graph(7) g.add_edge(0, 1, 3) g.add_edge(0, 2, 2) g.add_edge(1, 3, 4) g.add_edge(2, 3, 2) g.add_edge(3, 4, 4) g.add_edge(3, 5, 3) g.add_edge(4, 6, 2) g.add_edge(5, 6, 1) g.topological_sort() g.find_critical_path() print("Topological order:", g.get_topo_order()) print("Start time:", g.start_time) print("End time:", g.end_time) print("Critical path:", g.get_critical_path()) ``` 在上述代码中,我们首先定义了一个 Graph 类,其中包含邻接表、顶点数、每个顶点的入度、拓扑排序后的顺序、每个顶点的最早开始时间、最晚开始时间、关键路径等信息。然后定义了一些方法,包括添加边、获取入度、获取拓扑排序后的顺序、获取最早开始时间、最晚开始时间和关键路径等。其中,topological_sort() 方法实现了拓扑排序,find_critical_path() 方法实现了查找关键路径。 在主函数中,我们定义了一个 7 个顶点的 DAG,并添加了各个顶点之间的边。然后调用 topological_sort() 方法进行拓扑排序,再调用 find_critical_path() 方法查找关键路径。最后输出了拓扑排序后的顺序、每个顶点的最早开始时间、最晚开始时间和关键路径等信息。

相关推荐

最新推荐

recommend-type

数据结构经典代码(严蔚敏).

/* 图的关键路径问题的算法*/ /* 背包问题的贪心法算法*/ /* 用动态规划法求组和数的算法*/ /* 用回溯法解决骑士周游问题的算法*/ /* 0/1背包问题的回溯法算法*/ /* 0/1背包问题的动态规划法算法*/ /* 0/1背包问题的...
recommend-type

AOE_关键路径 源程序

图的应用 关于AOE网关键路径的算法 内容:按照图的“邻接表”存储结构表示AOE网,实现求其关键路径的算法
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

【实战演练】增量式PID的simulink仿真实现

# 2.1 Simulink仿真环境简介 Simulink是MATLAB中用于建模、仿真和分析动态系统的图形化环境。它提供了一个直观的用户界面,允许用户使用块和连接线来创建系统模型。Simulink模型由以下元素组成: - **子系统:**将复杂系统分解成更小的、可管理的模块。 - **块:**代表系统中的组件,如传感器、执行器和控制器。 - **连接线:**表示信号在块之间的流动。 Simulink仿真环境提供了广泛的块库,涵盖了各种工程学科,包括控制系统、电子和机械工程。它还支持用户自定义块的创建,以满足特定仿真需求。 # 2. Simulink仿真环境的搭建和建模 ### 2.
recommend-type

训练集和测试集的准确率都99%,但是预测效果不好

即使训练集和测试集的准确率都很高,但是在实际的预测中表现不佳,可能会有以下几个原因: 1. 数据质量问题:模型训练和测试的数据可能存在问题,比如数据标签错误、数据集采样不均衡、数据集中存在异常值等问题,这些问题可能会导致模型在实际预测中表现不佳。 2. 特征工程问题:模型的特征工程可能存在问题,导致模型无法很好地捕捉数据的特征,从而影响预测效果。 3. 模型选择问题:模型的选择可能不合适,比如选择的模型太简单,无法很好地拟合数据,或者选择的模型太复杂,导致过拟合等问题。 4. 超参数调整问题:模型的超参数可能没有调整到最佳状态,需要进行调整。 针对以上可能的原因,可以采取相应的措施进
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。
recommend-type

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依
recommend-type

【实战演练】MATLAB simulink船舶动力定位模拟器

# 1. MATLAB Simulink 简介** MATLAB Simulink 是 MathWorks 公司开发的一款图形化建模和仿真软件,广泛应用于工程、科学和教育领域。它提供了丰富的模块库和仿真环境,使工程师能够快速构建和仿真复杂系统。 Simulink 的核心概念是基于块状图建模,其中每个模块代表一个特定的功能或组件。用户可以通过拖放模块并连接它们来创建系统模型。Simulink 提供了广泛的模块库,涵盖了信号处理、控制系统、动力学和通信等领域。 此外,Simulink 还支持自定义模块开发,允许用户创建自己的模块来扩展其功能。这使得 Simulink 成为一个高度灵活的仿真平
recommend-type

linux下RS485怎么实现

在Linux下实现RS485通信,需要做以下几个步骤: 1. 确认硬件支持:首先需要确认通信设备硬件是否支持RS485通信,如果不支持需要更换支持RS485通信的硬件设备。 2. 配置串口参数:在Linux下使用RS485通信,需要对串口进行一些特殊的配置。例如,需要将串口设置为半双工模式、开启硬件流控等。可以使用Linux提供的stty命令或者相关API接口进行配置。 3. 编写应用程序:通过Linux提供的串口API接口,编写应用程序实现RS485通信。在应用程序中需要设置对应的串口参数,以及发送和接收数据的逻辑。 4. 配置硬件电平转换器:在使用RS485通信时,需要将串口的逻辑