C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)相关的知识,希望对你有一定的参考价值。

在这里插入图片描述基本思想是:
假设求从顶点vi到vj的最短路径。
如果从vi到vj有弧,则从vi到vj存在一条长度为arcs[i][j]的路径,该路径不一定是最短路径,尚需进行n次试探。
首先考虑路径(vi, v0, vj)是否存在(判别弧(vi, v0)和(v0, vj)是否存在)。
如果存在,则比较(vi, vj)和(vi, v0, vj)的路径长度,取长度较短者为从vi到vj的中间顶点的序号不大于0的最短路径。
假如在路径上再增加一个顶点v1,也就是说,如果(vi, …, v1)和(v1, …, vj)分别是当前找到的中间顶点的序号不大于0的最短路径,那么(vi, …, v1, … , vj)就有可能是从vi到vj的中间顶点的序号不大于1的最短路径。
将它和已经得到的从vi到vj中间顶点序号不大于0的最短路径相比较,从中选出中间顶点的序号不大于1的最短路径之后,再增加一个顶点v2,继续进行试探,依此类推。
在一般情况下,若(vi, …, vk)和(vk, …, vj)分别是从vi到vk和从vk到vj的中间顶点的序号不大于k-1的最短路径,则将(vi, …, vk, …, vj)和已经得到的从vi到vj且中间顶点序号不大于k-1的最短路径相比较,其长度较短者便是从vi到vj的中间顶点的序号不大于k的最短路径。
这样,在经过n次比较后,最后求得的必是从vi到vj的最短路径。
按此方法,可以同时求得各对顶点间的最短路径。

求任意两顶点间的最短路径Floyd算法如下:

#include <iostream>
using namespace std;

const int MAXW = 30000;
const int MaxVertexNum = 30;
typedef char VertexType;
class MGraph
{
public:
	void CreateGraph();
	void ShortestPath_Floyd();
	void Print_Path_Floyd(int v,int w);

private:
	int vertexnum;
	VertexType vertexs[MaxVertexNum];
	int edgenum;
	bool P[MaxVertexNum][MaxVertexNum][MaxVertexNum];
	int D[MaxVertexNum][MaxVertexNum];
	int arcs[MaxVertexNum][MaxVertexNum];
};

void MGraph::CreateGraph()
{
	cout << "请输入节点数和边条数" << endl;
	cin >> vertexnum >> edgenum;
	for (int i = 0; i < vertexnum; i++)
		for (int j = 0; j < vertexnum; j++)
			arcs[i][j] = MAXW;
	cout << "请依次输入按序号0到n顶点的中存储的信息" << endl;
	for (int i = 0; i < vertexnum; i++)
	{
		cin >> vertexs[i];
	}
	cout << "下面输入边的信息" << endl;
	for (int i = 0; i < edgenum; i++)
	{
		int v1, v2, w;
		cout << "输入边<i,j>对应的顶点序号i,j,然后再输入该边的权值" << endl;
		cin >> v1 >> v2 >> w;
		arcs[v1][v2] = w;
	}
}

void MGraph::ShortestPath_Floyd()
{//用Floyd算法求有向图G中各对顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]

	//若P[v][w][u] = 1,则u是从v到w当前求得的最短路径上的顶点

	for (int v = 0;v<vertexnum;v++)
		for (int w = 0; w < vertexnum; w++)
		{
			D[v][w] = arcs[v][w];
				for (int u = 0; u < vertexnum; u++) P[v][w][u] = 0;
			if (D[v][w] < MAXW)//从v到w有直接路径
			{
				P[v][w][v] = 1;
				P[v][w][w] = 1;
			}
		}
	for (int u = 0;u< vertexnum;u++)
			for (int v = 0;v<vertexnum;v++)
				for (int w = 0; w < vertexnum; w++)
				{
					if (D[v][u] + D[u][w] < D[v][w])
					{
						D[v][w] = D[v][u] + D[u][w];
						P[v][w][u] = 1;
					}
				}
}

void MGraph::Print_Path_Floyd(int v, int w)
{
	int i;
	for (i = 0; i < vertexnum; i++)
	if (i != v && i != w && P[v][w][i] == true) break;

		if (i >= vertexnum) cout << v << "->" << w << endl;
		else
		{
			Print_Path_Floyd(v, i);
			Print_Path_Floyd(i, w);
		}
}


int main()
{
	MGraph g;
	g.CreateGraph();
	g.ShortestPath_Floyd();
	int v, w;
	cin >> v >> w;
	g.Print_Path_Floyd(v, w);
	return 0;
}

在这里插入图片描述

以上是关于C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)的主要内容,如果未能解决你的问题,请参考以下文章

求有向图两个顶点间的最短路径的方法,用简单语言或举例描述。

单源点最短路径的Dijkstra算法

图 实验七 采用Dijkstra算法求带权有向图的最短路径

贪心算法(Dijkstra)解决单源最短路径问题(C++)

算法_最短路径

C++ 实现带权有向图的单源点最短路径Dijkstra算法(完整代码)