【图论】关键路径求法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.mzph.cn/news/164269.shtml

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

相关文章

代码随想录-刷题第五天

链表题目总结 链表基本操作 对链表进行增删改查等基本操作。注意&#xff0c;很多链表的题目使用虚拟头结点操作起来会更加方便。每次对应头结点的情况都要单独处理&#xff0c;所以使用虚拟头结点的技巧&#xff0c;就可以解决这个问题。 反转链表 可以使用头插法&#xf…

Shopee本土号封号几率大吗?如何避免封号?被封号了怎么办?

Shopee是近几年热门的电商平台之一&#xff0c;即使越来越多的跨境电商涌现&#xff0c;他的地位在东南亚市场依然占据一席之地&#xff0c;也依旧吸引着需要跨境商家入局。尤其在2023年&#xff0c;在TikTok Shop在印尼被关停之后&#xff0c;留下了大片空白&#xff0c;Shope…

CF 1890A Doremy‘s Paint 3 学习笔记 map的使用

原题 A. Doremys Paint 3 time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output An array &#x1d44f;1,&#x1d44f;2,…,&#x1d44f;&#x1d45b;&#xfffd;1,&#xfffd;2,…,&#xfffd;&a…

跨境电商必须要海外代理IP吗?盘点五大海外代理IP

相信跨境电商人近日都为了2023的跨境黑五旺季奋战&#xff0c;而2024也即将来临&#xff0c;对于跨境人的考验一波接着一波&#xff0c;根据Adobe Analytics的数据&#xff0c;2022年黑色星期五的销售额创下91.2亿美元新高&#xff0c;网络星期的销售额同样达到创纪录的113亿美…

『 C++类与对象 』多态之单继承与多继承的虚函数表

文章目录 &#x1fae7; 前言&#x1fae7; 查看虚表&#x1fae7; 单继承下的虚函数表&#x1fae7; 多继承下的虚函数表 &#x1fae7; 前言 多态是一种基于继承关系的语法,既然涉及到继承,而继承的方式有多种: 单继承多继承棱形继承棱形虚拟继承 不同的继承方式其虚表的形…

ToDesk提示通道限制 - 解决方案

问题 使用ToDesk进行远程控制时&#xff0c;免费个人账号最多支持1个设备同时发起远控&#xff0c;若使用此账号同时在2个设备发起远控&#xff0c;则会提示通道限制&#xff0c;如下图&#xff1a; 解决方案 方案1&#xff1a;断开其它远控 出现通道限制弹窗时&#xff0…

数据结构(超详细讲解!!)第二十四节 二叉树(下)

1.遍历二叉树 在二叉树的一些应用中&#xff0c;常常要求在树中查找具有某种特征的结点&#xff0c;或者对树中全部结点逐一进行某种处理。这就引入了遍历二叉树的问题&#xff0c;即如何按某条搜索路径访问树中的每一个结点&#xff0c;使得每一个结点仅且仅被访问一次。 …

python3实现tailf命令

由于windows上面没有类似linux上面的tailf命令&#xff0c;所以下面的python脚本来代替其能力。 tailf.py import re import timeimport os import argparsedef follow(thefile):thefile.seek(0, os.SEEK_END)while True:_line thefile.readline()if not _line:time.sleep(0…

RabbitMQ 搭建和工作模式

MQ基本概念 1. MQ概述 MQ全称 Message Queue&#xff08;[kjuː]&#xff09;&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 &#xff08;队列是一种容器&#xff0c;用于存放数据的都是容器&#xff0…

docker部署微服务

目录 docker操作命令 镜像操作命令 拉取镜像 导出镜像 删除镜像 加载镜像 推送镜像 部署 pom文件加上 在每个模块根目录加上DockerFile文件 项目根目录加上docker-compose.yml文件 打包&#xff0c;clean&#xff0c;package 服务器上新建文件夹 测试docker-compo…

基于springboot和微信小程序的流浪动物管理系统

基于springboot和微信小程序的流浪动物管理系统 内容简介 基于微信小程序实现的流浪动物管理系统&#xff0c;该系统针对用户与管理员两种角色进行开发。 1、提供流浪动物的信息查询功能&#xff0c;包括品种、年龄、性别、健康状况等&#xff0c;提供救助活动报名功能。 2…

5.1 PBR基础 BRDF介绍

基于物理的渲染&#xff08;Physically Based Rendering&#xff0c;PBR&#xff09;是指使用基于物理原理和微平面理论建模的着色/光照模型&#xff0c;以及使用从现实中测量的表面参数来准确表示真实世界材质的渲染理念。 一、反射率方程 理论基础放在参考链接里。 直接开始…

【uniapp】uniapp开发小程序定制uni-collapse(折叠面板)

需求 最近在做小程序&#xff0c;有一个类似折叠面板的ui控件&#xff0c;效果大概是这样 代码 因为项目使用的是uniapp&#xff0c;所以打算去找uniapp的扩展组件&#xff0c;果然给我找到了这个叫uni-collapse的组件&#xff08;链接&#xff1a;uni-collapse&#xff09…

超详细的接口测试

本文主要分为两个部分&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什么要做&#xff1f; 第二部分&#xf…

ShellCode漏洞

ShellCode漏洞 可以查看如下网址&#xff1a; https://www.cnblogs.com/kakadewo/p/12996878.html 定义&#xff1a; shellcode是一段用于利用软件漏洞而执行的代码&#xff0c;shellcode为16进制之机械码&#xff0c;以其经常让攻击者获得shell而得名。shellcode常常使用机…

老鸟总结,软件测试工程师职业发展规划路线,入门到冲击大厂...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试工程师发展…

YOCTO 下载repo工具失败解决办法

curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repocp repo ~/binchmod ax ~/bin/repo如果使用时报错&#xff0c; 切换ubuntu 到 python3 版本。gedit repo 修改repo默认链接地址&#xff1a;REPO_URL "https://gerrit.googlesource.com/git-repo"…

Spring AOP-面向切面编程概念

Spring AOP-面向切面编程概念 AOP&#xff08;面向切面编程&#xff09;是编程范式的一种&#xff0c;它允许程序员将横切关注点&#xff08;cross-cutting concerns&#xff09;模块化。在面向切面编程中&#xff0c;这些横切关注点通常体现为在多个点重复出现的代码&#xf…

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

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

面试cast:reinterpret_cast/const_cast/static_cast/dynamic_cast

目录 1. cast 2. reinterpret_cast 3. const_cast 3.1 加上const的情况 3.2 去掉const的情况 4. static_cast 4.1 基本类型之间的转换 4.2 void指针转换为任意基本类型的指针 4.3 子类和父类之间的转换 5. dynamic_cast 5.1 RTTI(Run-time Type Identification) 1.…