入门概念

  • 带权图:如下图所示,我们把边带有权值的图称为带权图
  • 可以将边的权值理解为两点之间的距离
  • 一张图中任意两点间会有不同的路径相连
  • 最短路径:最短路径就是指连接两点的这些路径中最短的一条

Floyed、Dijkstra、Bellman-Ford、SPFA可以有效地解决最短路径问题。
需要注意的是:边的权值可以为负。当出现负边权时,有些算法不适用
最短路径问题是图论中典型的问题,多数模型可以归结为一下三种

  • 管道铺设
  • 线路安装
  • 地图规划

问题引入

国庆期间,7535寝室计划去旅行。在出发前,寝室长查阅了地图,如下图,寝室长希望在出发前知道任意两个城市之间的最短路径。

那么,如何求解任意两点之间的最短路径呢?

Floyed算法

分析:如果要让任意两点之间(假设是a到b)的路程变短,只能引入第三个点(假设为k),通过点k进行中转即a -> k -> b,才可能缩短原来从顶点a到顶点b的路程。如在上图中,结点1到结点3的距离本来为6,但是引入结点2之后,这两个结点的距离就变为了5。有时候可能还不只一个中转点,而是经过两个点或者更多的点进行中转会更短,即a -> k1 -> k2 -> b或者a -> k1 -> k2 -> … …-> b。
例如:在不考虑其他结点的情况下,上图中的4号城市到3号城市的路程原本是e[4][3] = 12,但是如果通过1号城市中转4 -> 1 -> 3,那么路程将缩短为11(e[4][1] + e[1][3] = 5 + 6 = 11)。如果同时通过1号和2号两个城市中转的话,从4号城市到3号城市的路程会进一步缩短为10(e[4][1] + e[1][2] + e[2][3] = 5 + 2 + 3 = 10)。通过以上分析,我们发现每个顶点都有可能使得另外两个顶点之间的路程变短。模拟该过程:
首先,如何存储这个地图
可以用一个二维数组e来存储。比如1号城市到2号城市的路程为2,则设e[1][2] = 2。2号城市无法直接到达4号城市, 则设e[2][4] = ∞。另外,约定自己到自己的路程为0。最终,得到表示两个城市之间距离的二维数组:


假设现在只允许经过1号顶点中转,求任意两点之间(ij)的最短路径。只需要判定经过1号顶点中转的距离e[i][1] + e[1][j]是否比 i 到 j 的初始距离e[i][j]小。代码如下:

//经过1号顶点中转
for(i = 1;i <= n;i++)
{for(j = 1;j <= n;j++){//if (i到j的初始距离e[i][j] > 经过1号顶点中转的距离) 更新if(e[i][j] > e[i][1] + e[1][j])e[i][j] = e[i][1] + e[1][j];}
}

在只经过1号中转的情况下,任意两点之间的最短路径更新为下图:

既然可以允许经过1号结点中转,那么是否可以允许经过2号结点中转?显然是可以的。接下来,允许2号结点作为中转结点,任意两点之间的最短路径怎么求?我们需要在允许1号顶点作为中转结点的情况下,再判断允许2号顶点作为中转结点,是否可以使得 i 号顶点到 j 号顶点之间的路程变得更短,即判断经过2号结点之后的路程e[i][2] + e[2][j]是否比不经过2号结点的路程e[i][j]要小,代码如下:

//经过2号顶点中转
for(i = 1;i <= n;i++)
{for(j = 1;j <= n;j++){if(e[i][j] > e[i][2] + e[2][j])e[i][j] = e[i][2] + e[2][j];}
}

在经过1号和2号的中转的情况下,任意两点之间的最短路径更新为下图:

根据这样的规则,依次经过1号,2号,3号,4号四个顶点中转的情况下,求任意两点之间的最短路径,代码如下:

//经过1号顶点中转
for(i = 1;i <= n;i++)for(j = 1;j <= n;j++){if(e[i][j] > e[i][1] + e[1][j])e[i][j] = e[i][1] + e[1][j];//经过1号结点中转之后距离变小,更新}
//经过2号顶点中转
for(i = 1;i <= n;i++)for(j = 1;j <= n;j++){if(e[i][j] > e[i][2] + e[2][j])e[i][j] = e[i][2] + e[2][j];//经过2号结点中转之后距离变小,更新}
//经过3号顶点中转
for(i = 1;i <= n;i++)for(j = 1;j <= n;j++){if(e[i][j] > e[i][3] + e[3][j])e[i][j] = e[i][3] + e[3][j];//经过3号结点中转之后距离变小,更新}
//经过4号顶点中转
for(i = 1;i <= n;i++)for(j = 1;j <= n;j++){if(e[i][j] > e[i][4] + e[4][j])e[i][j] = e[i][4] + e[4][j];//经过4号结点中转之后距离变小,更新}

以上过程较繁琐,我们可以将以上过程写成三个for循环,代码如下:

for(k = 1;k <= n;k++)  //依次经过1~n中的n个点进行中转for(i = 1;i <= n;i++)for(j = 1;j <= n;j++){if(e[i][j] > e[i][k] + e[k][j])e[i][j] = e[i][k] + e[k][j];}

需要强调的是:用来循环中间点的变量k必须放在最外面一层循环

最终,得到任意两个结点之间的最短路径,如图所示:

Floyed算法总结:
Floyed算法可以算出任意两点的最短路径,可以处理带有负权边的图,但不能处理带有“负环”的图
什么是负环?如图所示:

e[1][1]本应等于0,如果采用Floyed算法更新最短路,e[1][1] = 2 + 3 - 6 = -1

Floyed算法的时间复杂度:O(n^3)

Floyed算法例题:

信奥一本通 1342

题目描述

平面上有n个点(n<=100),每个点的坐标均在-10000 ~ 10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。

输入

共n+m+3行,其中:
第一行为整数n。
第2行到第n+1行(共n行),每行两个整数x和y,描述了一个点的坐标。
第n+2行为一个整数m,表示图中连线的个数。
此后的m行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线。
最后一行:两个整数s和t,分别表示源点和目标点。

输出

一行,一个实数(保留两位小数),表示从s到t的最短路径长度。

输入样例

5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5

输出样例

3.41


AC代码:

本题需要注意的是,对于double数组,需要循环手动赋值无穷,而不能用memset

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 110;
double e[N][N];//e[i][j]表示结点i到结点j的最短距离struct node
{int x;//横坐标int y;//纵坐标
}pos[N];int main()
{//memset(e,inf,sizeof e);int n,m;scanf("%d",&n);//表示结点的个数for (int i = 1;i <= n;i++) scanf("%d%d",&pos[i].x,&pos[i].y);//输入第i个结点的横纵坐标for (int i = 1;i <= n;i++)for (int j = 1;j <= n;j++)e[i][j] = inf;scanf("%d",&m);while (m --){int p,q;scanf("%d%d",&p,&q);//连接两点double del_x = pos[p].x - pos[q].x;//第p个结点和第q个结点的横坐标之差double del_y = pos[p].y - pos[q].y;//第p个结点和第q个结点的纵坐标之差e[p][q] = e[q][p] = sqrt((double)pow(del_x,2) + (double)pow(del_y,2));//计算距离}for (int i = 1;i <= n;i++) e[i][i] = 0;//初始化//Floyed算法模板for (int k = 1;k <= n;k++)for (int i = 1;i <= n;i++)for (int j = 1;j <= n;j++)e[i][j] = min(e[i][j],e[i][k] + e[k][j]);int start,end;scanf("%d%d",&start,&end);printf("%.2f",e[start][end]);return 0;
}

算法基础14 —— 图论入门之弗洛伊德算法(Floyed + Dijkstra + Bellman-Ford + SPFA)相关推荐

  1. pagerank算法实现matlab,Matlab 入门及PageRank算法求解.ppt

    Matlab 入门及PageRank算法求解 矩阵运算 + 矩阵加 - 矩阵减 * 矩阵乘 / 矩阵左除 \ 矩阵右除 ^ 矩阵幂 维数相同才能加减:方 阵才能求幂. 注意左乘,右乘. a\b?求a* ...

  2. 【算法基础】常用的数据结构与算法

    学习了王争老师的数据结构与算法之美之后,比较有感触,他把我们常用的数据结构和算法都讲了一遍,而且讲的还不错.整理汇总一下作为笔记. 一.复杂度分析 非常重要.我们必须掌握,基本上要做到,简单代码能很快 ...

  3. 算法基础2 —— OJ入门以及暴力枚举

    常见的OJ术语 Accepted (AC)-- 成功过题 Wrong Answer (WA) -- 输出结果错,一般是算法有问题,需要重新考虑思路或者其他 Runtime Error (RE) -- ...

  4. 算法基础11 —— 树入门(二叉树的遍历以及构造 + 普通树转换成二叉树 + 例题 + 二叉树的一些操作)

    字符二叉树的遍历 对于以上二叉树 先序遍历为(根左右) : ABCDEFG 中序遍历为(左根右) : CBEDAFG 后序遍历为(左右根) : CEDBGFA 层序遍历:(从左往右.从上往下) ABF ...

  5. 【算法基础】十大经典排序算法(动图)

    算法分类 冒泡排序(重点) 选择排序 插入排序 归并排序(重点) 快速排序(重点) 堆排序(重点) 计数排序 基数排序 本文的重点排序方法在:冒泡排序,归并排序,快速排序,桶排序. 文末有学习资料免费 ...

  6. 【数据结构与算法基础】模式匹配问题与KMP算法

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  7. 算法基础(四)| 前缀和算法及模板详解

    ⭐写在前面的话:本系列文章旨在复习算法刷题中常用的基础算法与数据结构,配以详细的图例解释,总结相应的代码模板,同时结合例题以达到最佳的学习效果.本专栏面向算法零基础但有一定的C++基础的学习者.若C+ ...

  8. python程序设计与算法基础第二版课后答案_python算法与程序设计基础答案

    python算法与程序设计基础答案 更多相关问题 [单选] 农产品质量安全法所称农产品,是指来源于农业的(),即在农业活动中获得的植物.动物.微生物及其产品. [单选] 设有关系Students(学号 ...

  9. 【算法基础笔记】常用的排序算法的时间、空间复杂度,部分排序算法原理

    冒泡排序 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除了 ...

最新文章

  1. Android ProGuard使用要点!
  2. 转载:SqlServer数据库性能优化详解
  3. MongoDB 杭州用户会全记录(千寻位置、妈妈帮、阿里云专家等精彩分享)
  4. 设计模式(二)模板方法模式
  5. qt将光标相对于桌面的位置转换为相对于窗口的位置
  6. [转载] python中for语句用法_详解Python中for循环的使用_python
  7. 想在研发群里装?先学会这几个排查K8s问题的办法
  8. rstudio安装后打不开_R与RStudio最简单安装指南
  9. nginx的介绍和安装
  10. 如何创建表以及设计表需要注意什么,oracle五种限制
  11. php在线图片签名,ElementUi+Vue+Php+fpdf+fpdi 实现文档在线签订(图片水印、手写签名)...
  12. c语言求开平方标准库函数,关于C语言中的开方计算,首先想到的当然是sqrt()函数,让我们先来回顾一下它的基本用法: 头文件:#include math.hsqrt(...
  13. 编程语言都代表哪些国家?
  14. 宠物王国四java正版_宠物王国单机版正版
  15. 3DMax_界面介绍及基本工具使用
  16. 什么TDD,让它见鬼去吧!
  17. jsp70877婚庆策划婚车预订网站 双数据库 mysql版
  18. 【shell】shell脚本实战-for循环
  19. 微x怎么设置主题_滴答小技法 - 安卓端设置项梳理
  20. 让vue-cli初始化后的项目集成支持SSR

热门文章

  1. PTA~习题8-4 报数 (20分) 2020年11月
  2. 题解BZOJ 2563 阿狸和桃子的游戏 [贪心]
  3. 魔兽延迟最低的服务器,魔兽世界延迟高解决方法
  4. 实现财务自由的关键词汇
  5. 【报告分享】2022快手磁力金牛家居百货行业营销洞察报告-磁力引擎(附下载)
  6. Simulink开环控制都不稳----记录一次还没有解决的问题
  7. 深度学习中的类别激活热图可视化
  8. 百度直达号,一场自high的喜剧
  9. 记一次feign调用报错:feign.codec.DecodeException: Error while extracting response for type [java...
  10. js 根据时区转换日期格式