有向无环图-拓扑排序与关键路径(C语言)

有向无环图

概念:无环的有向图(DAG)。有向无环图常用来描述一个工程或系统的进行过程。一个工程可以分为若干个子工程,只要完成了这些子工程,就可以导致整个工程的完成。
拓扑排序和关键路径属于有向无环图的应用。

拓扑排序

AOV网
在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在有向图中若以顶点表示活动有向边表示活动之间的先后关系,这样的图简称为AOV网。

拓扑排序概念:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。我们称这样的顶点序列为一个拓扑序列。拓扑排序就是对一个有向图构造拓扑序列的过程。

思路

(1) 选择一个入度为0的顶点并输出之。
(2) 从网中删除此顶点及所有出边。
(3)循环执行以上两步,直到不存在入度为0的顶点为止。

判断:循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。

结构定义

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef char VertexType;  //顶点类型
typedef int EdgeType;    //边上权值
#define MAXVEX 100 // 最大顶点数

typedef struct EdgeNode {      //边表结点
	VertexType adjvex;                //领接点域,存储对应下标
//	EdgeType weight;             //存储权值,如果是非网图可以省略
	struct EdgeNode* next;    //指向下一个邻接点
}EdgeNode;

typedef struct VertexNode {    //顶点结点
	int in;                    //顶点人度
	VertexType data;           //顶点域
	EdgeNode* firstedge;      //边表头指针
}VertexNode;
typedef struct VertexNode AdjList[MAXVEX];  //邻接表类型

typedef struct {
	AdjList adjList;
	int numNodes, numEdges;   //图当前顶点数与边数
}GraphAdjList;

拓扑排序

/* 拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList* G)
{
	EdgeNode* e;
	int i, k, gettop;
	int top = 0;         //栈指针下标
	int count = 0;       //统计输出顶点个数
	int* stack;          //建栈将入度为 0的顶点入栈
	stack = (int*)malloc(G->numNodes * sizeof(int));
	for (i = 0; i < G->numNodes; i++)
		if (G->adjList[i].in == 0)          //将入度为 0的顶点入栈
			stack[++top] = i;
	while (top != 0)
	{
		gettop = stack[top--];           //出栈
		printf("%c -> ", G->adjList[gettop].data);     //打印此顶点
		count++;
		e = G->adjList[gettop].firstedge;
		while (e)            //对此顶点弧表遍历
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			G->adjList[k].in--;  //将 k号顶点邻接点的入度减 1
			if (!G->adjList[k].in)
				stack[++top] = k;  //如果为 0则入栈
			e = e->next;
		}
	}
	if (count < G->numNodes)
		return ERROR;
	else
		return OK;
}

拓扑排序全部代码(含有向邻接表)

我是用英文字母为顶点的,即 char VertexType; 顶点类型

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef char VertexType;  //顶点类型
typedef int EdgeType;    //边上权值
#define MAXVEX 100 // 最大顶点数

typedef struct EdgeNode {      //边表结点
	VertexType adjvex;                //领接点域,存储对应下标
//	EdgeType weight;             //存储权值,如果是非网图可以省略
	struct EdgeNode* next;    //指向下一个邻接点
}EdgeNode;

typedef struct VertexNode {    //顶点结点
	int in;                    //顶点人度
	VertexType data;           //顶点域
	EdgeNode* firstedge;      //边表头指针
}VertexNode;
typedef struct VertexNode AdjList[MAXVEX];  //邻接表类型

typedef struct {
	AdjList adjList;
	int numNodes, numEdges;   //图当前顶点数与边数
}GraphAdjList;


void CreateALGRAph(GraphAdjList*); //建立图的邻接表结构
int LocateVex(GraphAdjList, VertexType);  //查找顶点

/* 拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList*);
int main(void)
{
	GraphAdjList G;
	CreateALGRAph(&G);
//	printf("!!!!!!!!!!_%d_!!!!!!!!\n",TopologicalSort(&G));
/*	for (int i = 0; i < G.numNodes; i++) //打印邻接表
	{
		EdgeNode* e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e = G.adjList[i].firstedge;
		printf("%c:", G.adjList[i].data);
		while (e)
		{
			printf(" %c", e->adjvex);
			e = e->next;
		}
		printf("\n");
	}
*/
	return 0;
}

/* 建立图的邻接表结构 */
void CreateALGRAph(GraphAdjList* G)
{

	scanf("%d%d", &G->numNodes, &G->numEdges); //输入顶点数与边数

	for (int i = 0; i < G->numNodes; i++)  //建立顶点表
	{
		scanf(" %c", &G->adjList[i].data);
		G->adjList[i].in = 0;               //初始化
		G->adjList[i].firstedge = NULL;       //边表置为空
	}

	for (int k = 0; k < G->numEdges; k++)   //建立边表
	{
		VertexType v1, v2;
		int i, j;  //用来返回下标
		scanf(" %c %c", &v1, &v2); //输入一条边依附的两个顶点
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		EdgeNode* e1 = (EdgeNode*)malloc(sizeof(EdgeNode));   //生成边表结点(指针e1指向生成的内存空间)

		e1->adjvex = G->adjList[j].data;         //邻接序号

		/* 头插法 */
		e1->next = G->adjList[i].firstedge;     //e1指向当前顶点指向结点
		G->adjList[i].firstedge = e1;    //当前顶点指向e1
		G->adjList[j].in++;         //顶点入度加 1 
	}
}

/* 查找顶点 */
int LocateVex(GraphAdjList G, VertexType v)
{
	for (int i = 0; i < G.numNodes; i++)
		if (v == G.adjList[i].data)
			return i;
	return -1;
}

/* 拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList* G)
{
	EdgeNode* e;
	int i, k, gettop;
	int top = 0;         //栈指针下标
	int count = 0;       //统计输出顶点个数
	int* stack;          //建栈将入度为 0的顶点入栈
	stack = (int*)malloc(G->numNodes * sizeof(int));
	for (i = 0; i < G->numNodes; i++)
		if (G->adjList[i].in == 0)          //将入度为 0的顶点入栈
			stack[++top] = i;
	while (top != 0)
	{
		gettop = stack[top--];           //出栈
		printf("%c -> ", G->adjList[gettop].data);     //打印此顶点
		count++;
		e = G->adjList[gettop].firstedge;
		while (e)            //对此顶点弧表遍历
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			G->adjList[k].in--;  //将 k号顶点邻接点的入度减 1
			if (!G->adjList[k].in)
				stack[++top] = k;  //如果为 0则入栈
			e = e->next;
		}
	}
	if (count < G->numNodes)
		return ERROR;
	else
		return OK;
}

关键路径

AOE网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在带权有向图中若以顶点表示事件有向边表示活动边上的权值表示该活动持续的时间,这样的图简称为AOE网。

关键路径概念:我们把路径上各个活动所持续的时间之和称为路径长度,从源点(入度为0的顶点)到汇点(出度为0的顶点)具有最大路径长度的路径叫做关键路径

关键活动:在关键路径上的活动叫关键活动。

大话数据结构这里讲的通俗易懂
大话数据结构

思路

先定义 4个参数
• etv(vi)- 表示事件 vi最早发生时间
• ltv(vi)- 表示事件 vi最晚发生时间
• ete(ai)- 表示活动 ai最早发生时间
• lte(ai)- 表示活动 ai最晚发生时间

方法步骤

  1. 求etv(i)、ltv(j).

    从etv[0] = 0 开始向前递推
    etv[k] = max{etv[i] + len<v~i~,v~k~>}, k ≠ 0 且 <v~i~,v~k~>∈P[k]   P[k]表示所有到达顶点v~k~的弧的集合
    从ltv[k] = etv[k] (k = n - 1) 开始向后递推
    ltv[k] = min{ltv[j] - len<v~k~,v~j~>}, k < n - 1 且 <v~i~,v~k~>∈S[k]   S[k]表示所有从顶点v~k~出发的弧的集合
    
  2. 求ete(i)、lte(j).

  3. 找 lte(i) == ete(i) 的关键活动.(包含第2个步骤)
    (ete[i] 等于 lte[i] 即在关键路径上,上面的图讲的通俗易懂)

     设活动 ai用弧 <j, k> 表示,持续时间记为 len<v~j~, v~k~> ,
     则
     ete[i] = etv[j]
     lte[i] = ltv[k] - len<v~j~, v~k~>
     判断lte(i) 是否等于 ete(i)
    

结构定义

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef char VertexType;  //顶点类型
typedef int EdgeType;    //边上权值
#define MAXVEX 100 // 最大顶点数

/* 全局声明 */
int* etv, * ltv;  //事件最早发生时间和最晚发生时间数组
int* stack2;      //用于存储拓扑序列的栈
int top2;         //用于stack2的指针

typedef struct EdgeNode {      //边表结点
	VertexType adjvex;                //领接点域,存储对应下标
	EdgeType weight;             //存储权值,如果是非网图可以省略
	struct EdgeNode* next;    //指向下一个邻接点
}EdgeNode;

typedef struct VertexNode {    //顶点结点
	int in;                    //顶点人度
	VertexType data;           //顶点域
	EdgeNode* firstedge;      //边表头指针
}VertexNode;
typedef struct VertexNode AdjList[MAXVEX];  //邻接表类型

typedef struct {
	AdjList adjList;
	int numNodes, numEdges;   //图当前顶点数与边数
}GraphAdjList;

改进的拓扑排序,便于求关键路径

/* 改进的拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList* G)
{
	EdgeNode* e;
	int i, k, gettop;
	int top = 0;         //栈指针下标
	int count = 0;       //统计输出顶点个数
	int* stack;          //建栈将入度为 0的顶点入栈
	stack = (int*)malloc(G->numNodes * sizeof(int));
	for (i = 0; i < G->numNodes; i++)
		if (G->adjList[i].in == 0)          //将入度为 0的顶点入栈
			stack[++top] = i;
//---------------------主要改动点------------------------
	top2 = 0;                  //初始化
	etv = (int*)malloc(G->numNodes * sizeof(int));  //事件最早发生时间数组
	for (i = 0; i < G->numNodes; i++)
		etv[i] = 0;            //初始化
	stack2 = (int*)malloc(G->numNodes * sizeof(int));  //初始化拓扑序列栈
//-------------------------------------------------------
	while (top != 0)
	{
		gettop = stack[top--];           //出栈
		count++;
//--------------------------------
		stack2[++top2] = gettop;      //将弹出的顶点序号压入拓扑序列的栈
//--------------------------------	
		e = G->adjList[gettop].firstedge;
		while (e)            //对此顶点弧表遍历
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			G->adjList[k].in--;  //将 k号顶点邻接点的入度减 1
			if (!G->adjList[k].in)
				stack[++top] = k;  //如果为 0则入栈
//----------------------------------
			if ((etv[gettop] + e->weight) > etv[k])
				etv[k] = etv[gettop] + e->weight;
//----------------------------------
			e = e->next;
		}
	}
	if (count < G->numNodes)
		return ERROR;
	else
		return OK;
}

求关键路径,G为有向网,输出 G的各项关键活动

/* 求关键路径,G为有向网,输出 G的各项关键活动*/
void CriticalPath(GraphAdjList* G)
{
	EdgeNode* e;
	int i, gettop, k, j;
	int ete, lte;            //活动最早发生时间与最迟发生时间变量
	TopologicalSort(G);     //求拓扑序列,计算数组 etv和 stack2的值
	ltv = (int*)malloc(G->numNodes * sizeof(int));  //事件最晚发生时间数组
	for (i = 0; i < G->numNodes; i++)
		ltv[i] = etv[G->numNodes - 1];          //初始化ltv
	while (top2 != 0)
	{
		gettop = stack2[top2--];
		e = G->adjList[gettop].firstedge;
		while (e)
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			if (ltv[k] - e->weight < ltv[gettop])  //求各顶点事件最晚发生时间ltv
				ltv[gettop] = ltv[k] - e->weight;
			e = e->next;
		}
	}
    /* 求 ete, ltv和关键活动 */
	for (j = 0; j < G->numNodes; j++)
	{
		e = G->adjList[j].firstedge;
		while (e)
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			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);
			e = e->next;
		}
	}
}

关键路径全部代码(含有向权值邻接表)

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef char VertexType;  //顶点类型
typedef int EdgeType;    //边上权值
#define MAXVEX 100 // 最大顶点数

int* etv, * ltv;  //事件最早发生时间和最晚发生时间数组
int* stack2;      //用于存储拓扑序列的栈
int top2;         //用于stack2的指针

typedef struct EdgeNode {      //边表结点
	VertexType adjvex;                //领接点域,存储对应下标
	EdgeType weight;             //存储权值,如果是非网图可以省略
	struct EdgeNode* next;    //指向下一个邻接点
}EdgeNode;

typedef struct VertexNode {    //顶点结点
	int in;                    //顶点人度
	VertexType data;           //顶点域
	EdgeNode* firstedge;      //边表头指针
}VertexNode;
typedef struct VertexNode AdjList[MAXVEX];  //邻接表类型

typedef struct {
	AdjList adjList;
	int numNodes, numEdges;   //图当前顶点数与边数
}GraphAdjList;


void CreateALGRAph(GraphAdjList*); //建立图的邻接表结构
int LocateVex(GraphAdjList, VertexType);  //查找顶点

/* 拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList*);
/* 求关键路径,G为有向网,输出 G的各项关键活动*/
void CriticalPath(GraphAdjList*);
int main(void)
{
	GraphAdjList G;
	CreateALGRAph(&G);
	CriticalPath(&G);
	/*for (int i = 0; i < G.numNodes; i++) //打印邻接表
		{
			EdgeNode* e = (EdgeNode*)malloc(sizeof(EdgeNode));
			e = G.adjList[i].firstedge;
			printf("%c:", G.adjList[i].data);
			while (e)
			{
				printf(" %c", e->adjvex);
				e = e->next;
			}
			printf("\n");

		}
	*/
	return 0;
}

/* 建立图的邻接表结构 */
void CreateALGRAph(GraphAdjList* G)
{

	scanf("%d%d", &G->numNodes, &G->numEdges); //输入顶点数与边数

	for (int i = 0; i < G->numNodes; i++)  //建立顶点表
	{
		scanf(" %c", &G->adjList[i].data);
		G->adjList[i].in = 0;               //初始化
		G->adjList[i].firstedge = NULL;       //边表置为空
	}

	for (int k = 0; k < G->numEdges; k++)   //建立边表
	{
		VertexType v1, v2;
		int i, j;  //用来返回下标
		scanf(" %c %c", &v1, &v2); //输入一条边依附的两个顶点
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		EdgeNode* e1 = (EdgeNode*)malloc(sizeof(EdgeNode));   //生成边表结点(指针e1指向生成的内存空间)
		scanf("%d", &e1->weight);  //输入 v1与 v2的边的权值
		e1->adjvex = G->adjList[j].data;         //邻接序号

		/* 头插法 */
		e1->next = G->adjList[i].firstedge;     //e1指向当前顶点指向结点
		G->adjList[i].firstedge = e1;    //当前顶点指向e1
		G->adjList[j].in++;         //顶点入度加 1 
	}
}

/* 查找顶点 */
int LocateVex(GraphAdjList G, VertexType v)
{
	for (int i = 0; i < G.numNodes; i++)
		if (v == G.adjList[i].data)
			return i;
	return -1;
}

/* 改进的拓扑排序,如果 G有回路则输出 0,无回路输出 1 */
int TopologicalSort(GraphAdjList* G)
{
	EdgeNode* e;
	int i, k, gettop;
	int top = 0;         //栈指针下标
	int count = 0;       //统计输出顶点个数
	int* stack;          //建栈将入度为 0的顶点入栈
	stack = (int*)malloc(G->numNodes * sizeof(int));
	for (i = 0; i < G->numNodes; i++)
		if (G->adjList[i].in == 0)          //将入度为 0的顶点入栈
			stack[++top] = i;
//----------------------------------------------主要改动点
	top2 = 0;                  //初始化
	etv = (int*)malloc(G->numNodes * sizeof(int));  //事件最早发生时间数组
	for (i = 0; i < G->numNodes; i++)
		etv[i] = 0;            //初始化
	stack2 = (int*)malloc(G->numNodes * sizeof(int));  //初始化拓扑序列栈
//-------------------------------------------------------
	while (top != 0)
	{
		gettop = stack[top--];           //出栈
		count++;
//--------------------------------
		stack2[++top2] = gettop;      //将弹出的顶点序号压入拓扑序列的栈
//--------------------------------	
		e = G->adjList[gettop].firstedge;
		while (e)            //对此顶点弧表遍历
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			G->adjList[k].in--;  //将 k号顶点邻接点的入度减 1
			if (!G->adjList[k].in)
				stack[++top] = k;  //如果为 0则入栈
//----------------------------------
			if ((etv[gettop] + e->weight) > etv[k])
				etv[k] = etv[gettop] + e->weight;
//----------------------------------
			e = e->next;
		}
	}
	if (count < G->numNodes)
		return ERROR;
	else
		return OK;
}

/* 求关键路径,G为有向网,输出 G的各项关键活动*/
void CriticalPath(GraphAdjList* G)
{
	EdgeNode* e;
	int i, gettop, k, j;
	int ete, lte;            //活动最早发生时间与最迟发生时间变量
	TopologicalSort(G);     //求拓扑序列,计算数组 etv和 stack2的值
	ltv = (int*)malloc(G->numNodes * sizeof(int));  //事件最晚发生时间数组
	for (i = 0; i < G->numNodes; i++)
		ltv[i] = etv[G->numNodes - 1];          //初始化ltv
	while (top2 != 0)
	{
		gettop = stack2[top2--];
		e = G->adjList[gettop].firstedge;
		while (e)
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			if (ltv[k] - e->weight < ltv[gettop])  //求各顶点事件最晚发生时间ltv
				ltv[gettop] = ltv[k] - e->weight;
			e = e->next;
		}
	}
    /* 求 ete, ltv和关键活动 */
	for (j = 0; j < G->numNodes; j++)
	{
		e = G->adjList[j].firstedge;
		while (e)
		{
			k = 0;
			while (G->adjList[k].data != e->adjvex)  //查找 e->adjvex在 G->adjList[t].data的位置
			{
				k++;
			}
			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);
			e = e->next;
		}
	}
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言实现拓扑排序关键路径的方法如下: 1. 首先,需要定义一个有向无(DAG)来表示工程的活动和依赖关系。可以使用邻接矩阵或邻接表来表示。 2. 对于拓扑排序,可以使用深度优先搜索(DFS)算法来实现。具体步骤如下: - 创建一个栈来存储已经访问过的顶点。 - 从任意一个未访问的顶点开始,进行深度优先搜索。 - 在访问一个顶点时,先将其所有未访问的邻居顶点进行递归访问。 - 当一个顶点的所有邻居都被访问过后,将该顶点入栈。 - 最后,栈中的顶点的出栈顺序就是拓扑排序的结果。 3. 对于关键路径的计算,可以使用关键路径方法(Critical Path Method,简称CPM)来实现。具体步骤如下: - 首先,需要计算每个活动的最早开始时间(Earliest Start Time,简称EST)和最晚开始时间(Latest Start Time,简称LST)。 - EST表示在不延误整个工程的情况下,活动可以开始的最早时间。 - LST表示在不延误整个工程的情况下,活动必须开始的最晚时间。 - 活动的持续时间可以通过预先给定的数据进行计算。 - 最后,通过比较EST和LST,可以确定关键路径上的活动。 以下是一个示例代码,演示了如何使用C语言实现拓扑排序和计算关键路径: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 // 邻接表节点 typedef struct Node { int vertex; struct Node* next; } Node; // 创建邻接表节点 Node* createNode(int v) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->vertex = v; newNode->next = NULL; return newNode; } // 创建有向无 typedef struct Graph { int numVertices; Node** adjLists; } Graph; // 初始化有向无 Graph* createGraph(int vertices) { Graph* graph = (Graph*)malloc(sizeof(Graph)); graph->numVertices = vertices; graph->adjLists = (Node**)malloc(vertices * sizeof(Node*)); int i; for (i = 0; i < vertices; i++) graph->adjLists[i] = NULL; return graph; } // 添加边 void addEdge(Graph* graph, int src, int dest) { Node* newNode = createNode(dest); newNode->next = graph->adjLists[src]; graph->adjLists[src] = newNode; } // 拓扑排序的辅助函数 void topologicalSortUtil(Graph* graph, int v, int visited[], int stack[], int* top) { visited[v] = 1; Node* temp = graph->adjLists[v]; while (temp) { int adjVertex = temp->vertex; if (!visited[adjVertex]) topologicalSortUtil(graph, adjVertex, visited, stack, top); temp = temp->next; } stack[++(*top)] = v; } // 拓扑排序 void topologicalSort(Graph* graph) { int visited[MAX_SIZE] = {0}; int stack[MAX_SIZE]; int top = -1; int i; for (i = 0; i < graph->numVertices; i++) { if (!visited[i]) topologicalSortUtil(graph, i, visited, stack, &top); } printf("Topological Sort: "); while (top >= 0) { printf("%d ", stack[top--]); } printf("\n"); } // 计算关键路径 void criticalPath(Graph* graph, int source, int destination) { int numVertices = graph->numVertices; int* earliestStart = (int*)malloc(numVertices * sizeof(int)); int* latestStart = (int*)malloc(numVertices * sizeof(int)); // 初始化最早开始时间和最晚开始时间 int i; for (i = 0; i < numVertices; i++) { earliestStart[i] = 0; latestStart[i] = INT_MAX; } // 计算最早开始时间 topologicalSortUtil(graph, source, earliestStart, NULL, NULL); // 计算最晚开始时间 latestStart[destination] = earliestStart[destination]; for (i = numVertices - 1; i >= 0; i--) { int vertex = earliestStart[i]; Node* temp = graph->adjLists[vertex]; while (temp) { int adjVertex = temp->vertex; if (latestStart[adjVertex] - temp->weight < latestStart[vertex]) latestStart[vertex] = latestStart[adjVertex] - temp->weight; temp = temp->next; } } // 打印关键路径上的活动 printf("Critical Path: "); for (i = 0; i < numVertices; i++) { if (earliestStart[i] == latestStart[i]) printf("%d ", i); } printf("\n"); free(earliestStart); free(latestStart); } int main() { int numVertices = 6; Graph* graph = createGraph(numVertices); addEdge(graph, 0, 1); addEdge(graph, 0, 2); addEdge(graph, 1, 3); addEdge(graph, 2, 3); addEdge(graph, 3, 4); addEdge(graph, 4, 5); // 设置活动的持续时间 graph->adjLists[0]->weight = 2; graph->adjLists[1]->weight = 3; graph->adjLists[2]->weight = 1; graph->adjLists[3]->weight = 4; graph->adjLists[4]->weight = 2; graph->adjLists[5]->weight = 3; topologicalSort(graph); criticalPath(graph, 0, 5); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mirror_zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值