【图论】关键路径求法c++

news2024/9/22 15:48:38

代码结构如下图:
结构
其中topologicalSort(float**, int, int*, bool*, int, int)用来递归求解拓扑排序,topologicalSort(float**, int*&, int, int, int)传参图的邻接矩阵mat与结点个数n,与一个引用变量数组topo,返回一个布尔值表示该图是否存在拓扑排序,同时将引用变量数组topo赋值为该图的拓扑序列。

getEdges(float**, int**&, int)传参图的邻接矩阵mat,引用变量二维数组edge,结点数n。然后将返回该图的边数,同时将float赋值为一个存储图的边的起点与终点的edgeNum * 2维的数组。

aoe(float**, int, int*&, int&, float*&, float*&, float*&, float*&, int*&, int**&, int&)分别传参邻接矩阵mat,结点数n,引用变量criticalPath表示关键路径,引用变量ve,vl,e,l正如名字所示,topo与edges表示拓扑序列与边,edgeNum表示边的数量。

aoe(float**, int, int*&, int&, float*&, float*&, float*&, float*&)与上一个函数差不多,只是少了topo与edges,edgeNum两个参数,并且多了一个布尔类型的返回值,返回的是关键路径是否存在。

aoe(float**, int*&, int&)则更是只有三个参数,他不对ve,vl,e,l进行返回。

aoe

static const float INF = 1.0f/0.0f;

// x is what you are, and y is meaning to you are the no.y numbers to sort.
void topologicalSort(float** mat, int n, int* arr, bool* flags, int x=0, int y=0) {

	arr[y] = x;
	flags[x] = true;

	float tmp[n];

	// first, set all the elements of the no.x row to INF, and store the original value to tmp;
	// just like delete this vertex
	for (int i = 0; i < n; ++i) {
		tmp[i] = mat[x][i];
		mat[x][i] = INF;
	}

	for (int i = 0; i < n; ++i) {

		int k = (x + i) % n;

		// if k have not recorded in arr.
		if (!flags[k]) {

			bool flag = true;

			// this loop is aim to find a vertex whose in_degree is equals to 0.
			for (int j = 0; j < n; ++j) {
				if (j != k && mat[j][k] != INF) {
					flag = false;
					break;
				}
			}

			// if you delete x, the in_degree of k is equals to 0. so do a recursive call.
			if (flag) {
				topologicalSort(mat, n, arr, flags, k, y+1);
			}

		}

	}

	// restore the no.x row
	for (int i = 0; i < n; ++i) {
		mat[x][i] = tmp[i];
	}

}

bool topologicalSort(float** mat, int* &topo, int n, int x=0, int y=0) {

	topo = new int[n];
	bool *flags = new bool[n];

	for (int i = 0; i < n; ++i) {
		flags[i] = false;
	}

	topologicalSort(mat, n, topo, flags, x, y);

	for (int i = 0; i < n; ++i) {
		if (!flags[i]) return false;
	}

	return true;

}

int getEdges(float** mat, int** &edges, int n) {

	// e is for the edges, whose account is unsure
	// ans is for the number of edges
	int ans = 0;
	int** e = new int*[n * (n - 1)];

	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (i == j || mat[i][j] == INF) continue;
			e[ans++] = new int[]{i, j};
		}
	}

	// copy e into edges
	edges = new int*[ans];
	for (int i = 0; i < ans; ++i) {
		edges[i] = e[i];
	}

	delete[] e;

	return ans;

}

void aoe(float** mat, int n, int* &criticalPath, int &length, float* &ve, float* &vl, float* &e, float* &l, int* &topo, int** &edges, int &edgeNum) {

	ve = new float[n];
	vl = new float[n];
	e = new float[edgeNum];
	l = new float[edgeNum];

	for (int i = 0; i < n; ++i) {
		ve[i] = 0;
	}

	for (int i = 1; i < n; ++i) {

		int max = i;

		for (int j = 0; j < i; ++j) {
			if (mat[topo[j]][topo[i]] == 0 || mat[topo[j]][topo[i]] == INF) continue;
			if (ve[topo[j]] + mat[topo[j]][topo[i]] > ve[topo[max]] + mat[topo[max]][topo[i]]) {
				max = j;
			}
		}

		ve[topo[i]] = ve[topo[max]] + mat[topo[max]][topo[i]];

	}

	for (int i = 0; i < n; ++i) {
		vl[i] = ve[topo[n - 1]];
	}

	for (int i = n - 2; i >= 0; --i) {

		int min = i;

		for (int j = i + 1; j < n; ++j) {
			if (mat[topo[i]][topo[j]] == 0 || mat[topo[i]][topo[j]] == INF) continue;
			if (vl[topo[j]] - mat[topo[i]][topo[j]] < vl[topo[min]] - mat[topo[i]][topo[min]]) {
				min = j;
			}
		}

		vl[topo[i]] = vl[topo[min]] - mat[topo[i]][topo[min]];

	}

	for (int i = 0; i < edgeNum; ++i) {
		e[i] = ve[edges[i][0]];
		l[i] = vl[edges[i][1]] - mat[edges[i][0]][edges[i][1]];
	}

	int* critical = new int[n];
	critical[0] = topo[0];
	length = 1;

	for (int i = 0; i < n; ++i) {
		critical[i] = -1;
	}

	for (int i = 0; i < edgeNum; ++i) {
		float le = l[i] - e[i];
		if (le < 1e-32) {
			critical[edges[i][0]] = edges[i][1];
			length++;
		}
	}

	criticalPath = new int[length];
	int p = 0;
	int q = 0;

	while (p != -1) {
		criticalPath[q++] = p;
		p = critical[p];
	}

	delete[] critical;

}

bool aoe(float** mat, int n,  int* &criticalPath, int &length, float* &ve, float* &vl, float* &e, float* &l) {

	int* topo;
	int flag = topologicalSort(mat, topo, n);
	if (!flag) return false;
	int** edges;
	int edgeNum = getEdges(mat, edges, n);

	aoe(mat, n, criticalPath, length, ve, vl, e, l, topo, edges, edgeNum);

	return true;

}

bool aoe(float** mat, int n,  int* &criticalPath, int &length) {

	float* ve;
	float* vl;
	float* e;
	float* l;

	return aoe(mat, n, criticalPath, length, ve, vl, e, l);

}

在main函数中进行一个测试,传参如下图:

2
3
5
3
9
6
4
2
3
v1
v2
v3
v4
v5
v6
int main() {

	int n = 6;

	float** mat = new float*[] {
			new float[] {0,	2,		3,		INF,	INF,	INF	},
			new float[] {INF,	0,		INF,	5,		INF,	INF	},
			new float[] {INF,	3,		0,		9,		4,		INF	},
			new float[] {INF,	INF,	INF,	0,		6,		2	},
			new float[] {INF,	INF,	INF,	INF,	0,		3	},
			new float[] {INF,	INF,	INF,	INF,	INF,	0	}
	};

	char** value = new char*[n]{
		"v1", "v2", "v3", "v4", "v5", "v6"
	};

	float *ve, *vl, *e, *l;
	int* criticalPath;
	int length;

	int** edges;
	int* topo;

	topologicalSort(mat, topo, n);
	int edgeNum = getEdges(mat, edges, n);
	aoe(mat, n, criticalPath, length, ve, vl, e, l);

	cout << "拓扑排序为:";
	for (int i = 0; i < n; ++i) {
		cout << value[topo[i]] << " ";
	}
	cout << "\n\n";

	cout << "共有" << edgeNum << "条边:\n";
	for (int i = 0; i < edgeNum; ++i) {
		cout << value[edges[i][0]] << "->" << value[edges[i][1]] << ": " << mat[edges[i][0]][edges[i][1]] << endl;
	}
	cout << endl;

	for (int i = 0; i < n; ++i) {
		cout << '\t' << value[i];
	}
	cout << endl;

	cout << "ve:";
	for (int i = 0; i < n; ++i) {
		cout << '\t' << ve[i];
	}
	cout << endl;

	cout << "vl:";
	for (int i = 0; i < n; ++i) {
		cout << '\t' << vl[i];
	}
	cout << "\n\n";

	for (int i = 0; i < edgeNum; ++i) {
		cout << '\t' << value[edges[i][0]] << "->" << value[edges[i][1]];
	}
	cout << endl;

	cout << "e:";
	for (int i = 0; i < edgeNum; ++i) {
		cout << '\t' << e[i];
	}
	cout << endl;

	cout << "l:";
	for (int i = 0; i < edgeNum; ++i) {
		cout << '\t' << l[i];
	}
	cout << endl;

	cout << "l-e:";
	for (int i = 0; i < edgeNum; ++i) {
		cout << '\t' << l[i] - e[i];
	}
	cout << "\n\n";

	cout << "关键路径为:";
	for (int i = 0; i < length; ++i) {
		cout << value[criticalPath[i]] << " ";
	}

	return 0;

}

运行结果如下:
运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1244912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络奇缘】- 计算机网络|分层结构|ISO模型

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 计算机网络分层结构 OSI参考模型 OSI模型起源 失败原因: OSI模型组成 协议的作用 &#x1f4dd;全文…

C语言——求分段函数 y=f(x)的值

求分段函数 yf(x)的值,f(x)的表达式如下: #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int x,y;printf("请输入x的值&#xff1a;");scanf("%d",&x);if(x>5){yx3;}else if(x>0 && x<5){y0;}elsey2*x30;pr…

使用vcpkg安装库失败的解决方法

1、前言 vcpk是是一款开源的c/c库管理工具&#xff0c;尤其是在windows平台&#xff0c;可以帮助我们很好的管理各种依赖包。 在windows环境做c/c开发的人应该都深有体会&#xff0c;有时候编译需要下载一堆依赖库&#xff0c;导致搭建编译环境特别麻烦。但是&#xff0c;通过v…

深入理解Spring AOP的工作流程

文章目录 引言什么是AOP&#xff1f;Spring AOP的工作原理1. JDK动态代理2. CGLIB代理 Spring AOP的注解方式Aspect注解EnableAspectJAutoProxy注解 Spring AOP的工作流程拓展应用1. 自定义注解2. 异常处理3. 切面优先级 结论 &#x1f389;深入理解Spring AOP的工作流程 ☆* o…

vue - - - - - vue-qr插件生成二维码

vue-qr插件生成二维码 1. 安装插件2. 组件使用示例图&#xff1a;扫码结果 1. 安装插件 【vue-qr 官网地址】 npm install vue-qr --save // or yarn add vue-qr --save2. 组件使用 <template><vue-qr :logo-src"logoSrc":size"237":margin&qu…

Cache学习(2):Cache结构 命中与缺失 多级Cache结构 直接映射缓存

1 Cache名词解释 命中&#xff08;hit&#xff09;&#xff1a; CPU要访问的数据在Cache中有缓存缺失&#xff08;miss&#xff09;&#xff1a; CPU要访问的数据在Cache中没有缓存Cache Size&#xff1a;Cache的大小&#xff0c;代表Cache可以缓存最大数据的大小Cache Line&a…

Java设计模式系列:单例设计模式

Java设计模式系列&#xff1a;单例设计模式 介绍 所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法&#xff08;静态方法&#xff09; 比如 Hiberna…

西门子(Siemens)仿真PLC启动报错处理

目录 一、背景&#xff1a; 二、卸载软件 三、安装软件 三、启动软件 四、下载PORTAL项目 五、测试 一、背景&#xff1a; 在启动S7-PLCSIM Advanced V3.0仿真PLC时报错&#xff0c;报错信息为&#xff1a;>>Siemens PLCSIM Virtual Switch<<is misconfigu…

iframe内部子页面与外部主页面通讯

文章目录 一、问题二、解决2.1、子页面2.2、主页面 三、知识点3.1、[浏览器兼容性](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7)3.2、详解3.2.1、发送方3.2.2、接收方 一、问题 如上所示&a…

Vue3中如何响应式解构 props

目录 1&#xff0c;前言2&#xff0c;解决2.1&#xff0c;利用插件&#xff0c;实现编译时转换2.2&#xff0c;toRef 和 toRefs 1&#xff0c;前言 Vue3 中为了保持响应性&#xff0c;始终需要以 props.x 的方式访问这些 prop。这意味着不能够解构 defineProps 的返回值&#…

【云原生 Prometheus篇】Prometheus架构详解与核心组件的应用实例(Exporters、Grafana...)

Prometheus Part1 一、常用的监控系统1.1 简介1.2 Prometheus和zabbix的区别 二、Prometheus2.1 简介2.2 Prometheus的主要组件1&#xff09;Prometheus server2&#xff09;Exporters3&#xff09;Alertmanager4&#xff09;Pushgateway5&#xff09;Grafana 2.3 Prometheus的…

【性能优化】CPU利用率飙高与内存飙高问题

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…

解决:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解决&#xff1a;ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代码时&#xff0c;报错&#xff1a; from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 报错问题 from keras.optimizers import Adam I…

【赠书第7期】从零基础到精通Flutter开发

文章目录 前言 1 安装Flutter和Dart 2 了解Flutter的基础概念 2.1 Widget 2.2 MaterialApp和Scaffold 2.3 Hot Reload 3 编写你的第一个Flutter应用 3.1 创建一个Flutter项目 3.2 修改默认页面 3.3 添加交互 4 深入学习Flutter高级特性 4.1 路由和导航 4.2 状态管…

「 系统设计 」 为什么要做架构分层?

「 系统设计 」 为什么要做架构分层&#xff1f; 参考&鸣谢 3.设计模式之分层思维&#xff1a;为什么要做代码分层架构&#xff1f; 从零开始学架构&#xff08;八&#xff09;分层架构和设计模式 架构模式之分层架构总结 文章目录 「 系统设计 」 为什么要做架构分层&…

【libGDX】使用Mesh绘制立方体

1 前言 本文主要介绍使用 Mesh 绘制立方体&#xff0c;读者如果对 Mesh 不太熟悉&#xff0c;请回顾以下内容&#xff1a; 使用Mesh绘制三角形使用Mesh绘制矩形使用Mesh绘制圆形 在绘制立方体的过程中&#xff0c;主要用到了 MVP &#xff08;Model View Projection&#xff0…

<JavaEE> 什么是进程(Process)?进程管理,进程调度,内存管理,进程间通信和多进程编程

目录 一、进程&#xff08;Process&#xff09;的概念 二、进程管理 三、进程调度 四、内存管理 五、进程间通信 六、多进程编程 一、进程&#xff08;Process&#xff09;的概念 进程&#xff08;process&#xff09;也称为任务&#xff08;task&#xff09;&#xff0c…

sam和mobilesam的c#调用dll

这个主要注意&#xff1a; 我原本从一个地方把这个工程拷贝到另一个地方&#xff0c;然后我看了解决方案下的依赖项是有感叹号的&#xff0c;且这个时候代码出现很多下划的波浪红线。 然后我的做法如下&#xff1a; 然后我发现一直添加不了opencvsharp的dll文件&#xff0c;报…

Adiponectin 脂联素 ; T-cadherin +exosome

T-cadherin Adiponectin exosome T-cadherin Adiponectin exosome 代谢综合征中 外泌体、脂肪组织 和 脂联素 的器官间通讯-2019.pdf

基于IDEA+HTML+SpringBoot前后端分离电子商城

基于springboot的电子商城 项目介绍&#x1f481;&#x1f3fb; •B2C 商家对客户 •C2B2C 客户对商家对客户 1.1.1 B2C 平台运营方即商品的卖家 小米商城 •商品 •用户 1.1.2 C2B2C 平台运营方不卖商品&#xff08;也可以卖&#xff09; 卖家是平台的用户 买家也是平台用户 •…