算法导论 第二十五章:每对顶点间的最短路径

Floyd-Warshall 算法

   设G的顶点为V={1,2,...,n},对于每个k考虑顶点的一个子集{1,2,...,k}。对于任意一对顶点i,j ∈ V,考察 从i到 j 且中间顶点皆属于集合{1,2,...,k}的所有路径,设p是其中的一条最小权值路径:

1)如果k不是路径p中的中间顶点,则p的所有中间顶点皆在集合{1,2,...,k-1}中。因此从顶点i到顶点j且满足所有中间顶点皆属于集合{1,2,...k-1}的一条最短路径,也同样从顶点i到顶点j且满足所有中间顶点皆属于集合{1,2,...,k}的一条最短路径。

2)如果k是路径p的中间顶点,那么p可以分解成两部分,如下图。p1是从i到k的一条最短路径,且其所有中间顶点属于集合{1,2,...,k}。因为顶点k不是路径p1上的一个中间顶点,所以p1是从i到k的一条最短路径,且其所有中间顶点均属于集合{1,2,...,k-1}.类似地,p2是从顶点k到顶点j的一条最短路径,且其所有中间顶点均属于集合{1,2,...,k-1}


为从顶点i到顶点j,且满足所有中间顶点皆属于集合{1,2,...,k}的一条最短路径的权值,则有:

其中

伪代码如下:

运行时间:O(V^3)


完整代码:

#include<iostream>
#include<climits>
#include<iomanip>
using namespace std;

#define DG  0 
#define UDG 1
#define NIL -1

typedef int vType;
typedef int wType;
typedef struct edge{
	vType u;   // the start of edge
	vType v;   // the end of edge
	wType w;   //the weight of edge
	}edge;
typedef struct MGraph{
	int vNum;
	int eNum;
	vType *V;
	edge *E;
	wType **W;   //the weight matrix
	int kind;    // the type of the graph
	}MGraph;



void Matrix_Print(wType **M,int n)
{
	for(int i=0; i< n; i++)
	{
		for(int j=0; j<n; j++)
			cout<<setw(12)<<M[i][j];
		cout<<endl;
		}
	}
void Predecessor_Print(int **M,MGraph &G)
{
	for(int i=0; i<G.vNum; i++)
	{
		for(int j=0; j<G.vNum; j++){
			if(M[i][j]== NIL)
				cout<<setw(12)<<"NIL";
			else
				cout<<setw(12)<<G.V[M[i][j]];
			}
		cout<<endl;
		}
}
int Locate(MGraph &G,vType v)
{
	for(int i=0; i<G.vNum; i++)
		if(v == G.V[i])
			return i;
	return -1;
	}	
void Graph_Init(MGraph &G,vType V[],edge E[])
{
	//init the vertices 
	G.V = new vType[G.vNum];
	for(int i=0; i<G.vNum; i++)
		G.V[i] = V[i];
	//init the edge
	G.E = new edge[G.eNum];
	for(int i=0 ; i<G.eNum; i++){
		G.E[i].u = E[i].u;
		G.E[i].v = E[i].v;
		G.E[i].w = E[i].w;
		}
	//init the weight matrix
	G.W = new wType*[G.vNum];
	for(int i=0 ;i<G.vNum; i++)
		G.W[i] = new wType[G.vNum];

	for(int i=0; i<G.vNum; i++)
		for(int j=0; j<G.vNum; j++)
			if(i == j)
				G.W[i][j] = 0;
			else
				G.W[i][j] = INT_MAX;
	 for(int i=0; i<G.eNum; i++){
		int u_i = Locate(G,E[i].u);
		int v_i = Locate(G,E[i].v);
		G.W[u_i][v_i] = E[i].w;
		}
	}
wType **Matrix_Copy(wType **M,int n)
{
	wType **T = new wType*[n];
	for(int i=0; i<n; i++)
		T[i] = new wType[n];

	for(int i=0; i<n; i++)
		for(int j=0; j<n; j++)
			T[i][j] = M[i][j];
	return T;
	}

void Floyd_WarShall(MGraph &G)
{
	//when beginning ,D denote D[0] 
	wType **D = new wType*[G.vNum];
	for(int i=0; i<G.vNum; i++)
		D[i] = new wType[G.vNum];
	D = Matrix_Copy(G.W,G.vNum);

	// matrix tD store the (k-1)th result
	wType **tD = new wType*[G.vNum];   
	for(int i=0; i<G.vNum; i++)
		tD[i] = new wType[G.vNum];

	//when beginning,Pie denote Pie[0]
	int **Pie = new int*[G.vNum];
	for(int i=0; i<G.vNum; i++)
		Pie[i] = new int[G.vNum];

	for(int i=0;i<G.vNum; i++)
		for(int j=0; j<G.vNum; j++)
			if(i==j || D[i][j]==INT_MAX)
				Pie[i][j] = NIL;
			else
				Pie[i][j] = i;
	//matrix tPie store the (k-1)th result
	int **tPie = new int*[G.vNum];
	for(int i=0; i<G.vNum; i++)
		tPie[i] = new int[G.vNum];

	// D denote the (k)th result
	for(int k=0; k<G.vNum;  k++ ){
		tD = Matrix_Copy(D,G.vNum);
		for(int i=0; i<G.vNum; i++)
			for(int j=0; j<G.vNum; j++){ 
				if(tD[i][k]>=INT_MAX || tD[k][j]>=INT_MAX || tD[i][k]+tD[k][j]>= INT_MAX)
					D[i][j] = tD[i][j];
				else
					D[i][j] = min(tD[i][j],tD[i][k]+tD[k][j]);
				}
		cout<<"The "<<k+1<<"th roung weight matrix is:"<<endl;
		Matrix_Print(D,G.vNum);

		//Compute Matrix Pie
		tPie = Matrix_Copy(Pie,G.vNum);
		for(int i=0; i<G.vNum; i++)
			for(int j=0; j<G.vNum; j++){
				if(tD[i][k] == INT_MAX || tD[k][j] == INT_MAX || tD[i][k]+tD[k][j]>= INT_MAX)
				{
					Pie[i][j] = tPie[i][j];
					continue ;
					}
				if(tD[i][j] <= tD[i][k]+tD[k][j])
						Pie[i][j] = tPie[i][j];
				else
						Pie[i][j] = tPie[k][j];
				}
		cout<<"The "<<k+1<<"th round prececessor matrix is:"<<endl;
		Predecessor_Print(Pie,G);
		cout<<"----------------------------------------------"<<endl;
		}
	}
	
int main()
{
	vType V[]={1,2,3,4,5};
	edge  E[]={{1,2,3},{1,3,8},{1,5 ,-4},
	           {2,4,1},{2,5,7},{3,2,4},
			   {4,1,2},{4,3,-5},{5,4,6}
			   };
	MGraph G;
	G.vNum = sizeof(V)/sizeof(vType);
	G.eNum = sizeof(E)/sizeof(edge) ;
	G.kind = DG;
	Graph_Init(G,V,E);
	Floyd_WarShall(G);	
	return 0;
	}

运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值