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

代码结构如下图:
结构
其中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 vertexfor (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 rowfor (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 edgesint 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 edgesedges = 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.hqwc.cn/news/211615.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言数组的距离(ZZULIOJ1200:数组的距离)

题目描述 已知元素从小到大排列的两个数组x[]和y[]&#xff0c; 请写出一个程序算出两个数组彼此之间差的绝对值中最小的一个&#xff0c;这叫做数组的距离 。 输入&#xff1a;第一行为两个整数m, n(1≤m, n≤1000)&#xff0c;分别代表数组f[], g[]的长度。第二行有m个元素&a…

为什么你的自动化测试无法落地

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

[Android]使用Git将项目提交到GitHub

如果你的Mac还没有安装Git&#xff0c;你可以通过Homebrew来安装它&#xff1a; brew install git 方式一&#xff1a;终端管理 1.创建本地Git仓库 在项目的根目录下&#xff0c;打开终端&#xff08;Terminal&#xff09;并执行以下命令来初始化一个新的Git仓库&#xff1…

Centos7安装Cesi(Supervisor集中管理工具)

Background CeSi 是 Supervisor 官方推荐的集中化管理 Supervisor 实例的 Web UI&#xff0c;该工具是用 Python 编写&#xff0c;基于 Flask Web 框架 。Superviosr 自带的 Web UI 不支持跨机器管理Supervisor 进程&#xff0c;功能比较简单&#xff0c;通过 CeSi 可以集中管理…

Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!

Django Rest Framework&#xff08;DRF&#xff09;是构建强大且灵活的Web API的优秀工具。它基于Django&#xff0c;提供了一套用于构建Web API的组件和工具&#xff0c;简化了API开发过程&#xff0c;同时保留了Django的优雅和强大。 一、Web应用模式 在开发Web应用时&…

Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来 )

Jquery ajax 同步阻塞引起的UI线程阻塞的坑&#xff08;loading图片显示不出来&#xff0c;layer.load延迟&#xff09;jax重新获取数据刷新页面功能&#xff0c;因为ajax属于耗时操作&#xff0c;想在获取数据且加载页面时显示加载遮罩层&#xff0c;结果发现了ajax的好多坑。…

使用Wireshark提取流量中图片方法

0.前言 记得一次CTF当中有一题是给了一个pcapng格式的流量包&#xff0c;flag好像在某个响应中的图片里。比较简单&#xff0c;后来也遇到过类似的情况&#xff0c;所以总结和记录一下使用Wireshark提取图片的方法。 提取的前提是HTTP协议&#xff0c;至于HTTPS的协议需要导入服…

随笔记录-springmvc_ResourceHandlerRegistry+ResourceHttpRequestHandler

环境&#xff1a;springboot-2.7.5 配置文件配置静态资源映射 springboot配置静态资源映射方式是通过 WebMvcAutoConfiguration 实现的 spring: # resources: # # 自springboot 2.5.5之后&#xff0c;该属性已经被废弃&#xff0c;使用spring.web.resources.static-locat…

Android设计模式--适配器模式

至诚之道&#xff0c;可以前知 一&#xff0c;定义 适配器模式把一个类的接口变换成客户端所期待的另一种接口&#xff0c;从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 适配器模式在我们的开发中使用率极高&#xff0c;ListView&#xff0c;GridView&am…

redis运维(十八)pipeline

一 pipeline 流水线 说明&#xff1a; 这里讲解的不是jenkins的pipeline流水线这里pipeline: 管道 redis为什么要提供pipeline功能 事务和pipeline ① pipeline的理念 强调&#xff1a;单纯的pipeline跟事务没有关系redis-cli --pipe --> 使用了pipeline机制说明&a…

PPP/INS紧组合算法

前言&#xff1a;在学习紧组合之前学会GNSS/INS松组合是很有必要的&#xff0c;i2NAV团队开源的KF_GINS项目可以作为GNSS/INS松组合学习模板&#xff0c;本文章主要对武汉大学i2NAV发布的PPP/INS紧组合学习资源进行算法层面的总结&#xff0c;链接&#xff1a; 武汉大学多源智…