关键路径
与AOV-网相对的是AOE-网(即边表示活动的网)。AOE-网是一个带权的有向无环网,顶点表示事件,弧表示活动,权表示时间即活动持续的时间;AOE-网可用来估算工程的完成时间。
关键路径:路径最长的路径。
关键活动:活动(就是弧)最早开始时间==最晚开始时间
关键路径上的所有活动都是关键活动。
1.拓扑排序是解决一个工程能否顺序进行的问题
2.当需要计算一个工程完成的最短时间,就需要用关键路径
3.AOV网只能表示活动之间的制约关系,而AOE网可以用变得权值表示活动的持续时间。所以AOE网是建立在活动之间制约关系没有矛盾的基础上,再来分析整个工程需要多少时间
4.网中只有一个入度为0的顶点(称作源点)和一个出度为0的顶点(称作汇点)。
- 这里我们需要两个数组 ve[ ]:事件最早开始时间;vl[ ]:事件最晚开始时间
- 活动最早开始时间==ve[ ],活动最晚开始时间:vl[ ] - path[ 弧尾 ][ 弧头 ]
- 我们需要两个栈来帮助我们存储顶点,S栈存储所有入度为0的顶点,T栈用来返回一个全序序列
- 这里的top1与top2就是用来存储栈时用到的移动指针
- indegree[ ]用来存储每个顶点的入度
输入:
9 11
1 2 3 4 5 6 7 8 9
1 2 6
1 3 4
1 4 5
2 5 1
3 5 1
4 6 2
5 7 9
5 8 7
6 8 4
7 9 2
8 9 4
输出:
1 -> 2 : 6//由输出结果我们可以看出有两条关键路径
2 -> 5 : 1
5 -> 7 : 9
5 -> 8 : 7
7 -> 9 : 2//1->2->5->7->9
8 -> 9 : 4//1->2->5->8->9
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define MAX 65535//最大值
#define ver 20//预计最大顶点个数
int ve[ver];
int vl[ver];
int S[ver], T[ver];
int top1, top2;
typedef struct {
int adjvex;
struct NEXT* next;
}NEXT;
typedef struct {
int data;
NEXT* first;
}VEXTEX;
typedef struct {
VEXTEX arc[ver];
int vexnum, srcnum;
int indegree[ver];
int path[ver][ver];
}GRAPH;
//邻接表构图
void Create_Graph(GRAPH* G) {
NEXT* n;
scanf("%d %d", &G->vexnum, &G->srcnum);
for (int i = 1; i <= G->vexnum; i++) {
scanf("%d", &G->arc[i].data);
G->arc[i].first = NULL;
G->indegree[i] = 0;
}
for (int i = 1; i <= G->srcnum; i++) {
int v1, v2, weight;
scanf("%d %d %d", &v1, &v2, &weight);
G->path[v1][v2] = weight;
G->indegree[v2]++;
n = (NEXT*)malloc(sizeof(NEXT));
n->adjvex = v2;
n->next = G->arc[v1].first;
G->arc[v1].first = n;
}
}
int TgOrder(GRAPH* G) {
NEXT* n;
for (int i = 1; i <= G->vexnum; i++) {
if (!G->indegree[i]) {
S[++top1] = G->arc[i].data;
}
}
int count = 0;
while (top1 != 0) {
int elem = S[top1--];
T[++top2] = elem;
count++;
n = G->arc[elem].first;
while (n) {
if (!(--G->indegree[n->adjvex])) {
S[++top1] = G->arc[n->adjvex].data;
}
if (ve[n->adjvex] < ve[elem] + G->path[elem][n->adjvex]) {
ve[n->adjvex] = ve[elem] + G->path[elem][n->adjvex];
}
n = n->next;
}
}
if (count != G->vexnum) {
return 0;
}
else {
return 1;
}
}
void CriticalPath(GRAPH* G) {
if (!TgOrder(G)) {
printf("没有关键路径\n");
}
else {
NEXT* n;
for (int i = 1; i <= G->vexnum; i++) {
vl[i] = ve[G->vexnum];
}
while (top2) {
int elem = T[top2--];
n = G->arc[elem].first;
while (n) {
if (vl[elem] > vl[n->adjvex] - G->path[elem][n->adjvex]) {
vl[elem] = vl[n->adjvex] - G->path[elem][n->adjvex];
}
n = n->next;
}
}
for (int i = 1; i <= G->vexnum; i++) {
n = G->arc[i].first;
while (n) {
int k = G->path[i][n->adjvex];
int temp = ve[i] == vl[n->adjvex] - k ? 1 : 0;
if (temp == 1) {
printf("%d -> %d : %d\n", G->arc[i].data, G->arc[n->adjvex].data, k);
}
n = n->next;
}
}
}
}
int main()
{
GRAPH* G;
Create_Graph(&G);
TgOrder(&G);
CriticalPath(&G);
return 0;
}