数据结构 图(七)

关键路径


与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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值