图——基本的图算法(四)关键路径

1. 基本概念

(1)AOV网(Activity On Vertex Network)
AOV网是一个表示工程的有向图中,其中的顶点用来表示活动,弧则用来表示活动之间的优先关系。举个简单的例子,假定起床后可以边煮水,边刷牙洗脸,但洗脸要在刷牙后,煮好水,刷好牙洗好脸以后,就可以喝水了,这个活动的AOV图如下(其中的每个顶点都表示一个活动,而顶点之间的弧表示了活动之间的执行先后顺序):

(2)AOE网( Activity On Edge Network)
AOE网是一个表示工程的带权有向图,其中的顶点用来表示某个事件,弧用来表示活动,弧上的权值用来表示活动持续的时间。例如上述例子的AOE网如下:

(3)AOE网和AOV网的区别
AOV网:其顶点用来表示活动。AOE网是用来表示活动之间的制约关系。
AOE网:顶点表示事件,边表示活动,边上的权值用来表示活动持续的时间。AOV网是用来分析工程至少需要花多少时间完成,或是为了缩短时间需要加快哪些活动等问题。

(4)源点、汇点、路径长度
在AOE网中,
始点源点:入度为0的顶点,它表示一个工程的开始;
终点汇点:出度为0的顶点,它表示一个工程的结束;
路径长度:路径上各个活动所持续的时间之和。

(5)关键路径、关键活动
在AOE网中,从源点到汇点具有最大长度的路径称为关键路径,在关键路径上的活动称为关键活动

2. 关键路径算法

2.1 基本思想

(1)要找出一个AOE网中的关键路径,就要先找出网里的关键活动,这些关键活动间的路径就是关键路径。

(2)判断一个活动是不是关键活动,方法是要先找到所有活动的最早开始时间和最晚开始时间,并且对它们进行比较,如果二者相等(意味着这个活动在该工程中没有时间松动),说明这个活动是关键活动。

(3)对于活动<Vi, Vj>,它最早的开始时间等于事件Vi最早的发生时间earlist[Vi](事件v的最早发生时间用earlist[v])。假设E[Vi]表示所有到达顶点Vi的弧的集合,len<Vi, Vj>表示活动<Vi, Vj>的持续时间,那么:

注意,这里假设顶点下标从0开始,所以Vi==0,则表示它是源点,因此最早的开始时间为0;当某个顶点不是源点,那么只有在它前面的事件都发生完后,才能轮到这个事件,所以用了max。

(4)对于活动<Vi, Vj>,它最晚的开始时间等于事件Vj最晚的发生时间减去这个活动的持续事件,即latest[Vj]-len<Vi, Vj>(事件v的最晚的发生时间用latest[v])。假设S[Vj]表示所有从顶点Vj出发的弧的集合,len<Vj, Vk>表示活动<Vj, Vk>的持续时间,那么:

2.2 算法实现

(1)数据结构

typedef struct EdgeListNode{ //边表结点int adjId;int weight;EdgeListNode* next;
};typedef struct VertexListNode{ //顶点表结点int in; //入度int data;EdgeListNode* firstadj; //指向其边表
};typedef struct GraphAdjList{ //图结构int vertexnumber; //顶点个数int edgenumber;VertexListNode vertextlist[Maximum];
};

(2)具体实现
1)由基本思路可以知道,要求一个AOE网的关键路径,步骤如下:
A. 首先初始化每个顶点的最早开始为0,然后对AOE网进行拓扑排序,在排序的过程中获取每个顶点的最早开始时间;
B. 获取拓扑排序后,初始化每个顶点的最晚开始时间为汇点的最早开始时间,并从AOE网的汇点开始,从后往前,对每个顶点找到求其最晚开始时间;
C. 遍历图中的每条边(方法是遍历图中每个顶点的边表),求其最早开始时间和最晚开始时间,如果二者相等,则这是个关键活动,将其加入关键路径中。

2)代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
#include<sstream>
#include<list>
#include<stdlib.h>
#include<queue>
using namespace std;#define Maximum 1000typedef struct EdgeListNode{int adjId;int weight;EdgeListNode* next;
};typedef struct VertexListNode{int in;int data;EdgeListNode* firstadj;
};typedef struct GraphAdjList{int vertexnumber;int edgenumber;VertexListNode vertextlist[Maximum];
};//拓扑排序,返回拓扑排序结果,earlist存储每个顶点的最早开始时间
vector<int> ToplogicalSort(GraphAdjList g, int *earlist) {vector<int>v; //存储拓扑排序结果queue<int>q; //存储入度为0的顶点EdgeListNode *temp;int i, j, k, ans;ans = 0;v.clear();while(!q.empty()) {q.pop();}//找出所有入度为0的顶点for(i=1; i<=g.vertexnumber; i++) {if(g.vertextlist[i].in == 0) {q.push(i);}}while(!q.empty()) {i = q.front();v.push_back(i);q.pop();ans++;temp = g.vertextlist[i].firstadj;while(temp != NULL) {k = earlist[i] + temp->weight;if(k > earlist[temp->adjId]) {earlist[temp->adjId] = k;}j = --g.vertextlist[temp->adjId].in;if(j == 0) {q.push(temp->adjId);}temp = temp->next;}}if(ans < g.vertexnumber) {v.clear();}return v;
}//求关键路径,返回存储关键路径顶点的vector
vector<int> CriticalPath(GraphAdjList g) {vector<int>ans;vector<int>path;int i, j, k, *earlist, *latest;EdgeListNode *temp;//earlist存储每个顶点的最早开始时间//latest存储每个顶点的最晚开始时间earlist = (int*)malloc(sizeof(int) * (g.vertexnumber+1));latest = (int*)malloc(sizeof(int) * (g.vertexnumber+1));path.clear();for(i=1; i<=g.vertexnumber; i++) {earlist[i] = 0;}ans = ToplogicalSort(g, earlist);for(i=1; i<=g.vertexnumber; i++) {latest[i] = earlist[ans[g.vertexnumber-1]];}for(i=g.vertexnumber; i>0; i--) {temp = g.vertextlist[i].firstadj;while(temp!=NULL) {if(latest[temp->adjId] - temp->weight < latest[i]) {latest[i] = latest[temp->adjId] - temp->weight;}temp = temp->next;}}//遍历每条边for(i=1; i<=g.vertexnumber; i++) {temp = g.vertextlist[i].firstadj;while(temp != NULL) {j = earlist[i];k = latest[temp->adjId] - temp->weight;if(j == k) { //是关键活动//把该活动的两个顶点加入pathpath.push_back(i);path.push_back(temp->adjId);}temp = temp->next;}}return path;
}

(3)测试

int main() {GraphAdjList g;EdgeListNode *e;int i, j, k;g.vertexnumber = 5;g.edgenumber = 7;for(i=1; i<=g.vertexnumber; i++) {g.vertextlist[i].data = i;g.vertextlist[i].firstadj = NULL;}g.vertextlist[1].in = 0;g.vertextlist[2].in = 1;g.vertextlist[3].in = 2;g.vertextlist[4].in = 2;g.vertextlist[5].in = 1;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 2; e->weight = 2; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 4; e->weight = 1; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 5; e->weight = 1; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 3; e->weight = 3; e->next = g.vertextlist[2].firstadj; g.vertextlist[2].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 4; e->weight = 5; e->next = g.vertextlist[2].firstadj; g.vertextlist[2].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 3; e->weight = 8; e->next = g.vertextlist[4].firstadj; g.vertextlist[4].firstadj = e;e = (EdgeListNode*)malloc(sizeof(EdgeListNode));e->adjId = 3; e->weight = 1; e->next = g.vertextlist[5].firstadj; g.vertextlist[5].firstadj = e;vector<int>ans;ans = CriticalPath(g);for(i=0; i<ans.size(); i+=2) {cout<<ans[i]<<"->"<<ans[i+1]<<endl;}cout<<endl;return 0;
}

图——基本的图算法(四)关键路径相关推荐

  1. 数据结构--图(Graph)详解(四)

    数据结构–图(Graph)详解(四) 文章目录 数据结构--图(Graph)详解(四) 一.图中几个NB的算法 1.普里姆算法(Prim算法)求最小生成树 2.克鲁斯卡尔算法(Kruskal算法)求最 ...

  2. 中图杯获奖作品计算机组,“中图杯”第十四届环境地图大赛召开 地图慧成指定制图软件...

    2017年"中图杯"第十四届中国青少年环境地图大赛开赛,你准备好了么? 为了让青少年了解地图,学习地图,爱护环境,保护地球,这样的地图大赛是非常有意义的,每一届的比赛都受到非常多的 ...

  3. 基于图数据库、图算法、图神经网络的 ID Resolution/ID Mapping 大数据分析方法与代码示例

    本文首发于 NebulaGraph 公众号 "本文是一个基于 NebulaGraph 上的图数据库.图算法.图神经网络的 ID Resolution/ID Mapping 方法综述,除了基本 ...

  4. 计算机软件设计图ns图,PC梯形图的四种设计方法

    本文介绍了PC梯形图的四种设计方法,除此之外,还有其他一些方法,如经验法.在系统设 计中对不同的环节,可根据具体情况,采用不同的设计方法.通常在全局上采用程序框图及功能模块方法设计:在旧设备改造中,采 ...

  5. ❤️导图整理数组6:四数组的四数之和,详解Counter类实现哈希表计数,力扣454❤️

    此专栏文章是对力扣上算法题目各种方法的总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解. 目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), ...

  6. 图——基本的图算法(一)图的存储结构

    图--基本的图算法(一)图的存储结构 1. 图的存储结构概述 对于图G=(V, E)来说,可以有两种标准的表示方法,一个是邻接矩阵,另一个是邻接链表,这两种方法都可以表示有向图和无向图.除此之外,图的 ...

  7. 数据结构之图的应用(四)之关键路径

    前面已经分享完了图的应用的三种.这三种可以说是很重要的,涉及了几个重要算法.今天,我们来分享<数据结构与算法>书本里的图的第四种应用--关键路径.下面我们一起来看看吧 1.AOE网 在前一 ...

  8. 数据结构-----图的拓扑排序和关键路径算法

    部分图片取自:http://www.cnblogs.com/navorse/articles/1893863.html 在介绍拓扑排序和关键路径之前,先引入AOE网络的概念: 该图为一个AOE网,顶点 ...

  9. BUCT数据结构——图(拓扑排序、关键路径)

    文章目录 问题 A: 邻接矩阵存储的图,节点的出度和入度计算(附加代码模式) 问题 B: 算法7-12:有向无环图的拓扑排序 问题 C: 有向图是否存在环? 问题 D: 图-节点的最早发生时间 问题 ...

  10. 服务器显卡芯片,Intel服务器独立显卡官方美图:单卡四芯原来如此

    面向轻薄本.入门级台式机的Iris Xe MAX之后,Intel今天发布了又一款基于Xe LP低功耗架构的独立显卡"服务器GPU"(Server GPU),代号为DG1,面向高密度 ...

最新文章

  1. Oracle中的不等于号
  2. python函数参数类型及其顺序
  3. linux spidev 应用_Linux下SPI驱动的移植和应用程序的测试
  4. data()中的数据可以直接操作
  5. java对外接口开发实例
  6. 一个计算机软件学生的求职简历,计算机学生求职的个人简历模板
  7. 《教练型领导力》--司铭宇老师
  8. html表格中间有空白,word文档表格中间出现空白怎么解决
  9. 网页游戏外挂辅助AMF模拟通讯必备
  10. 汽车matlab小论文,基于matlab汽车道路模型研究论文
  11. 漂亮的在线Css字体
  12. 洛谷P1367 蚂蚁
  13. linux 五笔中文输入法,Linux下如何使用五笔和拼音,区位输入法
  14. 浅谈《英雄杀》5人局之反贼技巧
  15. 自学编程5个月找到了月薪12K的工作,我的方法值得大家借鉴
  16. 融云韩迎:中国技术型公司出海才刚开始,未来有很大发展空间
  17. 在线购物系统1.1分析类图
  18. 高斯白噪声中CW,LFM脉冲检测,定量画ROC曲线
  19. 上市公司财务报告的那点事(5):从新手试练到股票建仓,美丽的老板出海卖电器
  20. 下雪啦 也用Matlab实现大雪纷飞 Matlab雪花

热门文章

  1. CAD中 OLE不能旋转_AutoCAD中光栅图像和OLE图像,究竟如何选择
  2. 8051单片机的C语言程序设计
  3. STM32神舟III号 驱动直流电机学习(三 )
  4. 广东女子职业技术学院计算机应用技术,广东女子学院虚拟校园系统的构建与技术实现...
  5. 几种免杀转储lsass进程的技巧
  6. python anacoda更换国内镜像源和常用软件包管理操作详细讲解(已爬坑)
  7. debian 5常用软件包名称,及安装方法
  8. AI上推荐 之 FM和FFM(九九归一)
  9. 计算机网络实验教程金伟祖,基于PDCA循环的计算机网络实验教学改革
  10. java编程 科学计算器_可编程科学计算器下载-可编程科学计算器(Scientific Calculator Plus) 安卓版v1.7.2.60-pc6手机下载...