图论算法总结之三:最短路径算法

三、最短路径算法

对于带权值的图,从一点到另外一点的权值和(距离和)最小是多少,最短路径算法讨论的就是这样的问题

提前说一句,负权值的回路是没有最短路的,因为每绕一圈最短路都会减少

也补一句,所谓最短路径的最优子结构,就是说设s[i][j]是从i到j的权值和,当s[i][j]最小的时候记为p[i][j],那么这条路所经过的k,满足p[i][j]=p[i][k]+p[k][j],(注意k在i->j的路径上,这一点很重要,很多博客举a地到b地的最短距就是a地到c地的最短距加上c地到b地的最短距都是很明显的错误说法,想想三角形的三边。。。)用反证法是很容易证明的

1.Floyd-Warshall

①思路:对于两点之间的最短路,存在经过某一点中转和不经过该点中转两种选择,我们通过对这两种做法的选择判断来更新已有的最短路,当所有的情况都分析过之后,留下的便是最短路

②实现:用dis[num][num]存最短路,一开始dis里面存的都是初始化时得到的权值,先看所有的最短距用第0个节点中转是否会产生更小的距离(比如第i个节点到第j个节点dis[i][j]?dis[i][0]+dis[0][j]),更小的话,就更新;再看第1个节点,这个时候直接如法炮制,在上一次处理过的矩阵上重复操作(dis[i][j]?dis[i][1]+dis[1][j])即可;在之后以此类推,直到每一个点作为中转的情况都考虑到,得到的就是最短路

③说明:为什么可以在之前更新过的矩阵上直接开始下一轮更新?比如dis[i][1]+dis[1][j],在讨论是否i->1->j比i->j更好的时候,其实i->0->1 and i->1 ; 1->0->j and 1->j孰大孰小我们已经判断过了,这样对于i->j的最短路可能情况,在我们已经讨论的中转点里(0 和1)里面我们只用讨论1了,之后的分析以此类推,可以说明这样做的正确性

④代码:

int dis[num][num],G[num][num];
int main(){
	//省略输入数据初始化图矩阵的过程 
	for(int i=0;i<num;i++)
		for(int j=0;j<num;j++)
			dis[i][j]=G[i][j];
	//Floyd		
	for(int k=0;k<num;k++){//枚举中转点 
		for(int i=0;i<num;i++){//这两重循环是更新最短距的 
			for(int j=0;j<num;j++){
				if(dis[i][j]>dis[i][k]+dis[k][j])
					dis[i][j]=dis[i][k]+dis[k][j];
			}
		}
	}
	return 0;
} 

⑤时间复杂度:三种循环,假设点数是N,时间复杂度为O(N^3)

⑥局限性:虽然实现容易,时间复杂度太大

2.Dijkstra

假设一个图里面没有负权边,固定一个起点讨论最短路问题

①思路&#x

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值