Floyd Algorithm

Floyd算法又称为,插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法。通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。Floyd算法使用三个for循环就可以解决问题,所以它的时间复杂度为O(n^3)。但是要弄清楚三个循环的顺序。

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

过程如下:

1.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min(G[i,j], G[i,k]+G[k,j]),如果G[i,j]的值变小,则D[i,j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。

然而,如下的循环顺序是错误的

for ( int i = 0; i < 节点个数; ++i )
{
    for ( int j = 0; j < 节点个数; ++j )
    {
        for ( int k = 0; k < 节点个数; ++k )
        {
            if ( Dis[i][k] + Dis[k][j] < Dis[i][j] )
            {
                // 找到更短路径
                Dis[i][j] = Dis[i][k] + Dis[k][j];
            }
        }
    }
}

因为最短距离一共有三种情况,

1.两点的直达距离最短。
2.两点间只通过一个中间点而距离最短。
3.两点间用通过两各以上的顶点而距离最短。

上述循环方式对于第三种情况可能会出错。因为如果把检查所有节点X放在最内层,这样会过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。比如下图的情形


所以,我们需要改写循环顺序,如下:

for ( int k = 0; k < 节点个数; ++k )
{
    for ( int i = 0; i < 节点个数; ++i )
    {
        for ( int j = 0; j < 节点个数; ++j )
        {
            if ( Dis[i][k] + Dis[k][j] < Dis[i][j] )
            {
                // 找到更短路径
                Dis[i][j] = Dis[i][k] + Dis[k][j];
            }
        }
    }
}

这样一来,对于每一个节点X,我们都会把所有的i到j处理完毕后才继续检查下一个节点。

完整的code

#include<iostream>
const int Maxm=10000;
using namespace std;


int p, q, k, m;
int Vertex, Line[Maxm];
int Path[Maxm][Maxm], Dist[Maxm][Maxm];
void Root(int p, int q)
{
	if (Path[p][q]>0)
	{
		Root(p, Path[p][q]);
		Root(Path[p][q], q);
	}
	else
	{
		Line[k] = q; k++;
	}
}
int main()
{
	memset(Path, 0, sizeof(Path));
	memset(Dist, 0, sizeof(Dist));
	cin >> Vertex;
	for (p = 0; p != Vertex; p++)
		for (q = 0; q != Vertex; q++)
			cin >> Dist[p][q];
	for (k = 0; k != Vertex; k++)
		for (p = 0; p != Vertex; p++)
			if (Dist[p][k]>0)
				for (q = 0; q != Vertex; q++)
					if (Dist[k][q]>0)
					{
						if (((Dist[p][q]>Dist[p][k] + Dist[k][q]) || (Dist[p][q] == 0)) && (p != q))
						{
							Dist[p][q] = Dist[p][k] + Dist[k][q];
							Path[p][q] = k;
						}
					}
	for (p = 0; p != Vertex; p++)
	{
		for (q = p + 1; q <= Vertex; q++)
		{
			cout << "\n==========================\n";
			cout << "Source:" << p << '\n' << "Target" << q << '\n';
			cout << "Distance:" << Dist[p][q] << '\n';
			cout << "Path:" << p; k = 2; Root(p, q);
			for (m = 2; m <= k - 1; m++)
				cout << "-->" << Line[m]; cout << '\n';
			cout << "==========================\n";
		}
	}
	return 0;
}


完成以下代码:""" File: fromexample.py Project 12.9 Defines and tests the all pairs shortest paths algorithm of Floyd. Uses the graph from Figure 12.19 of the text, as represented in the file example.txt. """ from graph import LinkedDirectedGraph import random from arrays import Array # Functions for working with infinity def isLessWithInfinity(a, b): """Returns False if a == b or a == INFINITY and b != INFINITY. Otherwise, returns True if b == INFINITY or returns a < b.""" if a == LinkedDirectedGraph.INFINITY and b == LinkedDirectedGraph.INFINITY: return False elif b == LinkedDirectedGraph.INFINITY: return True elif a == LinkedDirectedGraph.INFINITY: return False else: return a < b def addWithInfinity(a, b): """If a == INFINITY or b == INFINITY, returns INFINITY. Otherwise, returns a + b.""" if a == LinkedDirectedGraph.INFINITY or b == LinkedDirectedGraph.INFINITY: return LinkedDirectedGraph.INFINITY else: return a + b def minDistance(a, b): if isLessWithInfinity(a, b): return a else: return b # Define a function that uses Floyd's algorithm def allPairsShortestPaths(matrix): """ please complete the Floyd algorithm here """ pass # Define a function to print a labeled distance matrix def printDistanceMatrix(matrix, table): """Prints the distance matrix with rows and columns labels with the index positions and vertex labels.""" labels = Array(len(table)) index = 0 labelWidth = 0 indexWidth = 0 for label in table: labels[table[label]] = label labelWidth = max(labelWidth, len(str(label))) indexWidth = max(indexWidth, len(str(index))) index += 1 weightWidth = 0 for row in range(matrix.getHeight()): for column in range(matrix.getWidth()): weightWidth = max(weightWidth, len(str(matrix[row][column]))) weightWidth = max(weightWidth, labelWidth, indexWidth) topRowLeftMargin
04-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值