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

这篇具有很好参考价值的文章主要介绍了【图论】关键路径求法c++。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代码结构如下图:
c++计算网络图的关键路径,图论,算法,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 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函数中进行一个测试,传参如下图:

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;

}

运行结果如下:
c++计算网络图的关键路径,图论,算法,c++,数据结构文章来源地址https://www.toymoban.com/news/detail-780598.html

到了这里,关于【图论】关键路径求法c++的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构的应用场景:如社交网络、路由算法、图论、网络协议等

    作者:禅与计算机程序设计艺术 数据结构(Data Structure)是计算机科学中存储、组织、管理数据的方式,主要用于解决信息检索、处理和运算时的效率及空间占用问题。它是指数据元素(elements)之间的关系、顺序和逻辑结构,以及相互作用的算法。数据结构通常采用抽象数据类

    2024年02月14日
    浏览(35)
  • 【算法每日一练]-图论(保姆级教程篇12 tarjan篇)#POJ3352道路建设 #POJ2553图的底部 #POJ1236校园网络 #缩点

    目录: 今天知识点 加边使得无向图图变成双连通图 找出度为0的强连通分量 加边使得有向图变成强连通图 将有向图转成DAG图进行dp          POJ3352:道路建设         思路: POJ2553:图的底部 思路: POJ1236校园网络 思路: 缩点:  思路:          由于道路要维修

    2024年02月05日
    浏览(37)
  • 图论与算法(2)图的基本表示

    (1) 有向图和无向图: 有向图(Directed Graph):图中的边具有方向,表示节点之间的单向关系。 无向图(Undirected Graph):图中的边没有方向,表示节点之间的双向关系。 (2)加权图和无权图: 加权图(Weighted Graph):图中的边具有权重或距离,表示节点之间的关系有一定

    2024年02月04日
    浏览(33)
  • 图论与算法(3)图的深度优先遍历

    图的遍历 是指按照一定规则访问图中的所有顶点,以便获取图的信息或执行特定操作。常见的图遍历算法包括深度优先搜索(DFS)和广度优先搜索(BFS)。 深度优先搜索 (DFS):从起始顶点开始,递归或使用栈的方式访问相邻的顶点,直到所有顶点都被访问过为止。DFS通过

    2024年02月06日
    浏览(41)
  • 图论与算法(5)图的广度优先遍历应用

    树的广度优先遍历(Breadth-First Traversal),也称为层次遍历,是一种按层次顺序逐级访问树节点的遍历方式。在广度优先遍历中,先访问树的根节点,然后按照从上到下、从左到右的顺序逐层访问树的节点。 首先将树的根节点入队列,然后循环执行以下操作:出队列一个节点

    2024年02月08日
    浏览(32)
  • 408【数据结构】图、生成树、图的出度和入度、路径and路径长度和回路、简单路径和简单回路概念整理 和 错题整理

            图由顶点集V和边集E组成,记为G=(V,E),使用 V(G) 表示 所有顶点的集合(不能为空) ;使用 E(G) 表示 各个顶点之间的关系(可以为空) 。若用V={v1,v2,v3,....,vn}来表示图,则使用 |V|表示图中顶点的个数, 使用E={(vi,vj)|vi∈V,vj∈V},用 |E| 表示图中 边的条

    2024年02月03日
    浏览(33)
  • 【算法基础:搜索与图论】3.2 树与图的dfs和bfs

    要学会建树、建图的通用方法。 dfs 和 bfs 的代码框架。 https://www.acwing.com/problem/content/848/ 在 dfs 的过程中,统计各个节点作为断点时的连通块最大值。 https://www.acwing.com/problem/content/849/ 看到最短距离就可以想到使用宽搜。 注意! :题目中说明了 a 和 b 表示存在一条从 a 走到

    2024年02月16日
    浏览(29)
  • 数据结构——关键路径

    ——本节内容为Bilibili王道考研《数据结构》P67视频内容笔记。 目录 一、基本概念 1.AOE网 2.AOE网的性质  3.关键路径 4.最早最晚时间 二、求关键路径 1.步骤 2.举例 三、关键活动/路径特性 1.AOE网         在带权有向图中,以顶点表示事件,以有向边表示活动,以边上的权值表

    2024年02月07日
    浏览(35)
  • 数据结构--6.2关键路径

    AOE网:         在一个表示工程的带权有向图中,用顶点表示事件,用有向边上的权值表示活动表示持续时间,这种有向图的边表示活动的网,我们称为AOE网(Activity On Edge Network)。 我们把AOE网中没有入边的顶点称为始点或源点,没有出边的顶点称为终点或汇点。   ——

    2024年02月09日
    浏览(30)
  • 【图论】计算图的n-hop邻居个数,并绘制频率分布直方图

    在图论中,n-hop邻居(或称为K-hop邻居)是指从某个顶点出发,通过最短路径(即最少的边数)可以到达的所有顶点的集合,其中n(或K)是这个最短路径的长度。换句话说,n-hop邻居就是在图中,从一个顶点出发,经过n步可以到达的所有顶点。 举个日常生活中的例子,我们的

    2024年04月28日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包