最短路径问题(单源点和多源点)

最短路径问题(单源点和多源点)

单源点

  • Bellmanford算法
  • Dijkstra算法

多源点

  • 动态规划
  • FloyWarshall算法

单源点

Bellmanford算法

算法思想:
先初始化距离数组d[ ] = INF ,d[1] = 0 。
根据d[v] = min( d[u] + w[u][v] , d[v] ),对所有的边进行"松弛",值得注意,每一轮松弛都会更新至少一条最短路径,即得到一个最小的 d[i]。
时间复杂度: O(|V|*|W|)

Bellmanford(G, w, s)
{
	Init(G);//初始化,包括设置距离数组d[ ],且d[s] = 0;
	
	//进行n-1次全面“松弛”,每次至少找到了一条最短路径。
	for(int i=1; i < |V|; i++){ 
		for( (u,v) in G ){
			Relax(u,v,w);
		}
	}
	//检验是否有负权边
	for( (u,v) in G ){
		if( d[v] > d[u] + w[u,v] )	return false;
	}
	return true;
}

Relax(u,v,w){
	if( d[v]  >  d[u] + w[u,v]) 
		d[v]  =  d[u] + w[u,v];	 //更新(“松弛”)距离
		parent[v]  = u; 		//记录v上一个节点
}

Dijkstra算法(迪杰斯特拉算法)

算法思想:
维持一个数组的d[ N ]记录各个点到源点的距离, s[ N ]记录已经访问过的点,1代表已经访问,0代表未访问。
每次从未访问的点中选出 最小的d[i] , 并对其子节点进行更行距离。通过N次选取、更行后,即完成了计算所有点到单源点的距离。其中,也可以用parent[N]数组记录父节点。
时间复杂度: n次取出, 每次查找n, 总时间O(n*n)

(思考:数组d[N]可以换成一个最优队列,每次取出最优队列的最小值,更新新的d[] 时也可以在最优队列中更新)

//伪代码:
Dijkstra(){
	Init(G);
	//	s[ 1...N ] = {0}; s[1] = 1;
	Q =  V;  //初始化最优队列
	
	while( !Q.empty() ){
		u =ExtractMin(Q);
		for( v in Adj[u] ){
			Relax(u,v,w);
		}
	}
	
}

多源点

类似矩阵乘法的动态规划算法

设 i 到 j 的最短路径p 途径 k,路径p(i,j)=min (p(i,k)+w(k,j)), k=1…n 。
思考递归方程,进而可以理解动态规划思想。
D(i,j)(m) = min( D(i,k)(m-1)+w(k,j) ), k= 1…n

D(i,j)(m)代表第m次更新矩阵
注意第m次更新矩阵,至少可以得到路径长为m的最优路径
时间复杂度: n^4

Dynamic() //动态规划
{
	D(i,j)(0) = 0或者INF;  //初始化距离矩阵D(0)
	for( int m = 0; m<= n -1; m++)
		for( int i = 1; i<= n; k++)
			for( int j = 1; j<= n; k++)
				for( int k = 1; k<= n; k++)
					D(i,j)= min( D[i][k] + W[k][j] ,D[i][j])
	return D(n);
}

FloyWarshall算法(弗洛伊德算法)

算法思想:
找中间节点k;设 i 到 j 的最短路径p 途径 1,2,3… k。那么,若点k在p上,可以将路径p分成 p1: i***k 和 p2:k***j;
即 d(i,j) (k)= min( d(i,j) (k-1), d(i,k)(k-1)+d(k,j)(k-1) )
( d(i,j)(k) 代表点i 到 点j 途径 的点在1…k中,且d(i,j)(0) = w(i,j) )
时间复杂度:n^3

FloyWarshall()
{
	D(0) = W;  //初始化距离举证D(0)
	for( int k = 1; k<= n; k++)
		for( int i = 1; i<= n; k++)
			for( int j = 1; j<= n; k++){
					d(i,j) = min( d(i,j) , d(i,k)+d(k,j) )
			}
	
	return D(n);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值