上一篇文章的拓扑排序主要是为了解决一个工程能否顺利进行的问题,但有时我们还需要解决工程完成需要的最短时间的问题。

在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网成为AOE网(Acitivity On Edge Network)。

AOE网具有这样的特性,在某顶点所代表的事件发生后,从该顶点出发的各活动才能开始。只有在进入某顶点的各活动都已经结束,该顶点所代表的事件才能发生。

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

只有缩短关键路径上关键活动的时间才可以减少整个工期长度。

只需要找到所有活动的最早开始时间和最晚开始时间,并且比较它们,如果相等就意味着此活动是关键活动,活动间的路径为关键路径。如果不等,则就不是。

以下程序在DEV C++下编译运行通过。

#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 20int *etv,*ltv;//事件最早发生时间和最迟发生时间数组int *Stack2;//用于存储拓扑序列的栈int top2;//用于Stack2的指针 typedef struct EdgeNode
{int adjvex;//邻接点域,存储该顶点对应的下标 int weight;//权值 struct EdgeNode *next;//链域,指向下一个邻接点
}EdgeNode;
typedef struct VertexNode
{int in;//顶点入度char data;//顶点域,存储顶点信息EdgeNode *firstedge;//边表头指针
}VertexNode,AdjList[MAXVEX];
typedef struct
{AdjList adjList;int numVertexes,numEdges;
}GraphAdjList;void CreateALGraph(GraphAdjList *G)
{int i,j,k,w;EdgeNode *e;printf("输入顶点数和边数:\n");scanf("%d,%d",&G->numVertexes,&G->numEdges);getchar();for(i=0;i<G->numVertexes;i++){printf("输入第%d个顶点的值和入度:\n",i+1);scanf("%c,%d",&G->adjList[i].data,&G->adjList[i].in);G->adjList[i].firstedge=NULL;getchar();} for(k=0;k<G->numEdges;k++){printf("输入第%d条有向边(vi,vj)上的顶点序号和权值:\n",k+1);scanf("%d,%d,%d",&i,&j,&w);e=(EdgeNode*)malloc(sizeof(EdgeNode));e->adjvex=j;e->weight=w;e->next=G->adjList[i].firstedge;G->adjList[i].firstedge=e;}
}int TopologicalSort1(GraphAdjList *G)
{EdgeNode *e;int i,k,gettop;int top=0;//用于栈指针下标int count=0;//用于统计输出顶点的个数int *Stack;//建栈存储入度为0的指针Stack=(int*)malloc(G->numVertexes*sizeof(int));for(i=0;i<G->numVertexes;i++){if(G->adjList[i].in==0)Stack[++top]=i;//将入度为0的顶点的序号入栈 } top2=0;etv=(int *)malloc(G->numVertexes*sizeof(int));//时间最早发生时间数组for(i=0;i<G->numVertexes;i++){etv[i]=0;//初始化为0 } Stack2=(int *)malloc(G->numVertexes*sizeof(int));while(top!=0){gettop=Stack[top--];//printf("%c->",G->adjList[gettop].data);count++;Stack2[++top2]=gettop;//将弹出的顶点序号压入拓扑序列的栈 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])){etv[k]=etv[gettop]+e->weight;}}}if(count<G->numVertexes)return -1;else return 0;
}void CriticalPath(GraphAdjList *G)
{EdgeNode *e;int i,gettop,k,j;int ete,lte;//声明活动最早发生时间和最迟发生时间变量ltv=(int *)malloc(G->numVertexes*sizeof(int));for(i=0;i<G->numVertexes;i++)ltv[i]=etv[G->numVertexes-1];//初始化ltv
//  printf("top2:%d\n",top2);
//  for(i=0;i<10;i++)
//      printf("Stack2[%d]:%d",i,Stack2[i]);while(top2!=0) //计算ltv{gettop=Stack2[top2--];//将拓扑序列出栈for(e=G->adjList[gettop].firstedge;e;e=e->next){k=e->adjvex;if(ltv[k]-e->weight<ltv[gettop])ltv[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("<%c,%c> length: %d,",G->adjList[j].data,G->adjList[k].data,e->weight);}}
}
void main()
{GraphAdjList G;CreateALGraph(&G);TopologicalSort1(&G);//求拓扑序列,计算数组etv和Stack2的值CriticalPath(&G);
}

运行结果如下图所示。

输入第9条有向边(vi,vj)上的顶点序号和权值:

4,7,4

整个算法的时间复杂度为O(n+e)。

C语言实现图的关键路径算法相关推荐

  1. 第5-6课:关键路径算法

    作为一个项目经理或工程总监,他最关心的两个问题就是工程是否能顺理进行和整个工程的最短完成时间.第5-2课讲了拓扑排序算法,对应了第一个问题的解决方案,这一课将介绍关键路径算法,就是为了解决第二个问题, ...

  2. c语言遍历算法的头文件,图优先遍历算法(C语言版).doc

    图优先遍历算法(C语言版) 众炼向饭桨泞奉源柿虐萧宰徽强药邻摘甭膜酣猖椅支习洋瞪较效笋盏厚婪跳博险僳乘措笆却问谬闸皇机兽偿谐芹违邹竞芬襟竣备烘令救汇邵叙鹰扭肾钙苏辅捕先是埠郧苛三驯溅烂右井准刮修柒拿苇 ...

  3. DAG 图关键路径算法

    关键路径 如果DAG图拓扑有序,那么此图可以转换成线性的先后关系,而不需要回退去访问数据.如果项目安排的事件拓扑有序,那么此项目中的各个事件的依存关系不可以解耦,不会形成连环套而致使项目无法开展.项目 ...

  4. 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径

    文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...

  5. 【数据结构】什么的图的关键路径?关键路径相关概念?关键路径算法实现?

    目录 一.什么是关键路径? 1.现实问题 二.关键路径相关概念? 三.关键路径算法实现? 1.算法分析 2.算法步骤 3.算法实现 一.什么是关键路径? 关键路径:若有向图中,各顶点表示事件,各有向边 ...

  6. 大话数据结构 第七章 图(二) 最小生成树、最短路径、拓扑排序、关键路径算法

    大话数据结构 第七章 图(二) 最小生成树.最短路径.拓扑排序.关键路径算法 最小生成树 定义 Prim算法 Kruskal算法 最短路径 Dijkstra算法 Floyd算法 拓扑排序 AOV网 拓 ...

  7. 数据结构(廿五) -- C语言版 -- 图 - 图的遍历 -- 邻接矩阵 - 深度/广度优先遍历/搜索(DFS、BFS)

    内容预览 零.读前说明 一.概 述 二.深度优先遍历(DFS) 2.1.无向图的遍历过程 2.2.有向图的遍历过程 2.3.总结说明 2.4.实现源代码 三.广度优先遍历(BFS) 3.1.广度优先的 ...

  8. 数据结构(廿六) -- C语言版 -- 图 - 图的遍历 -- 邻接表 - 深度/广度优先遍历/搜索(DFS、BFS)

    内容预览 零.读前说明 一.深度优先遍历 1.1.深度优先的遍历过程 1.2.深度优先的遍历实现代码 二.广度优先遍历 2.1.广度优先的遍历过程 2.2.广度优先的遍历实现代码 三.源码测试效果 3 ...

  9. 有向无环图之关键路径

    **有向无环图之关键路径** 1 AOE-网:边表示活动的网.AOE-网是一个带权的有向无环图,其中顶点表示事件,弧表示活动,权表示活动持续的时间. 2 通常AOE-网可用来估算工程的完成时间. 例图 ...

  10. 图的深度搜索c语言,求图的深度优先搜索!该怎么处理

    当前位置:我的异常网» C语言 » 求图的深度优先搜索!该怎么处理 求图的深度优先搜索!该怎么处理 www.myexceptions.net  网友分享于:2013-03-16  浏览:12次 求图的 ...

最新文章

  1. 如何用两种方式同时实现ListBox的滚动功能
  2. SVN,桌面右击-settings-Icon Overlays 选择 None
  3. selenium webdriver模拟鼠标键盘操作
  4. [导入]ASP常用函数:getIMG()
  5. php socket 多次发送,php模拟socket 多次发送数据的实现方法
  6. 网络KPI异常检测之时序分解算法
  7. LeetCode简单题目(#27 #28 #35 #38)-2019.10.23-4道
  8. CF1082E Increasing Frequency (multiset+乱搞+贪心)
  9. python爬虫实例100例-10个python爬虫入门实例
  10. 2021年主流CAD批量打印软件功能对比
  11. 美服fgo显示服务器异常,FGO日服美服错误代码合集_FGO日服美服错误代码汇总_牛游戏网...
  12. MTK6577+Android GPIO
  13. Redis面试宝典12道法
  14. STM32F103_study67_The punctual atoms(STM32 OLED display experiment)
  15. python selenium 跳转网页_selenium关于页面跳转
  16. log buffer及日志管理深入分析及性能调整(七)
  17. 微信小程序图片在不同设备显示保持图片比例并且居中
  18. C语言实现文件的加密解密
  19. 1,Nginx负载均衡策略upstream,六种策略
  20. 超级好用的7个程序员笔记软件,你最常用的是哪个?

热门文章

  1. HBase二级索引实现方案
  2. IIS无法启动:存储空间不足解决办法
  3. 蓝桥杯单片机学习之数码管
  4. 【STM32H7的DSP教程】第7章 ARM DSP源码和库移植方法(IAR8)
  5. 电工与电子技术和电子电工的区别
  6. 【历史上的今天】10 月 11 日:域名 baidu.com 问世;三星 Galaxy Note 7 爆炸门告一段落;图灵奖数据库先驱诞生
  7. 干货!10分钟,用Python生成图文并茂的PDF报告!
  8. Java Swing开发 Label标签 界面中文出现乱码解决方案
  9. SP刷机工具错误信息
  10. 用netbean搭建第一个struts的web项目