最短路(Floyd,dijkstra)

Floyd

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
Floyd是最简单的最短路径算法,可以计算图中任意两点间的最短路径。时间复杂度为N的3次方,适用于出现负边权的情况。

for(int k = 1;k <= n;k ++)
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k][j]);
//Floyd算法模板

算法步骤:枚举中间断点k,让后枚举起点,终点。如果起点到断点的距离加断点到终点的距离小于了起点到终点的距离,则说明从起点到终点的最短路径可以变为起点到断点后再走断点到终点,并且这样走的距离小于原来起点到终点的距离。
输出路径:
Floyd算法输出路径也是采用记录前驱点的方式。因为floyd是计算任意两点间最短路径的算法,dis[i][j]记录从i到j的最短路径值。故我们定义pre[i][j]为一个二维数组,记录从i到j的最短路径中,j的前驱点是哪一个。递归还原路径。
更新若floyd最短路有更新,那么pre[i][j]=pre[k][j];

void print(int x){
    if(pre[s][x]==0) return;
    print(pre[s][x]);
    printf(->%d”,x);
}
    for(int k = 1;k <= n;k ++)
	for(int i = 1;i <= n;i ++)
	for(int j = 1;j <= n;j ++)
	if(a[i][j] > a[i][k] + a[k][j])
	a[i][j] = a[i][k] + a[k][j],prev[i][j] = prev[k][j];

dijkstra

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止,时间复杂度为N方。

void dijkstra() {
	for(int i = 1;i <= n;i ++) {
		int minn = 0x3f3f3f3f,tmp;
		for(int j = 1;j <= n;j ++)
		if(!vis[j] && dis[j] < minn) {
			minn = dis[j];
			tmp = j;
		}
		vis[tmp] = 1;
		for(int j = 1;j <= n;j ++)
		if(dis[j] > dis[tmp] + a[j][tmp])
		dis[j] = dis[tmp] + a[j][tmp];
	}
}
//dijkstra算法模板

Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。
步骤:
①在没有被访问过的点中找一个相邻顶点k,使得dis[k]是最小的;
②k标记为已确定的最短路vis[k]=true;
③用for循环更新与k相连的每个未确定最短路径的顶点v (所有未确定最短路的点都松弛更新)
“松弛”操作:
原来用一根橡皮筋直接连接a、b两点,现在有一点k,使得a->k->b比a->b的距离更短,则把橡皮筋改为a->k->b ,这样橡皮筋更加松弛。
代码实现:

if(dis[b]>dis[k]+w[k][b])
dis[b]=dis[k]+w[k][b];	

最短路(Floyd,dijkstra)_第1张图片
算法流程:
最短路(Floyd,dijkstra)_第2张图片
最短路(Floyd,dijkstra)_第3张图片
最短路(Floyd,dijkstra)_第4张图片
最短路(Floyd,dijkstra)_第5张图片
最短路(Floyd,dijkstra)_第6张图片
最短路(Floyd,dijkstra)_第7张图片
最短路(Floyd,dijkstra)_第8张图片
最短路(Floyd,dijkstra)_第9张图片

你可能感兴趣的:(最短路)