今天来讲点图论的知识,来看看最短路径的一个求法(所有的求法我以后会写,也有可能咕咕咕)

你们都说图看着没意思不好看,那今天就来点情景

 
       
 
暑假,_GC准备去一些城市旅游。有些城市之间有公路,有些城市之间则没有,如下图。为了节省经费以及方便计划旅程,_GC希望在出发之前知道任意两个城市之前的最短路程。
 (好吧它还是图)
 
        上图中有4个城市8条公路,公路上的数字表示这条公路的长短。请注意这些公路是单向的(无向图也一样)。我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径。这个问题这也被称为“多源最短路径”问题。
 
        现在需要一个数据结构来存储图的信息,我们仍然可以用一个4*4的矩阵(二维数组e)来存储。比如1号城市到2号城市的路程为2,则设e[1][2]的值为2。2号城市无法到达4号城市,则设置e[2][4]的值为∞(为什么是无穷呢,这个后面讲)。另外此处约定一个城市自己是到自己的也是0(部分题目有所不同),例如e[1][1]为0,具体如下。
        现在回到问题:如何求任意两点之间最短路径呢?通过之前的学习我们知道通过深度或广度优先搜索可以求出两点之间的最短路径。所以进行n^2遍深度或广度优先搜索,即对每两个点都进行一次深度或广度优先搜索,便可以求得任意两点之间的最短路径。可是还有没有别的方法呢?(毕竟暴力很恶心啊)
 我们来想一想,根据我们以往的经验,如果要让任意两点(例如从顶点a点到顶点b)之间的路程变短,只能引入第三个点(顶点k),并通过这个顶点k中转即a->k->b,才可能缩短原来从顶点a点到顶点b的路程。那么这个中转的顶点k是1~n中的哪个点呢?甚至有时候不只通过一个点,而是经过两个点或者更多点中转会更短,即a->k1->k2b->或者a->k1->k2…->k->i…->b。比如上图中从4号城市到3号城市(4->3)的路程e[4][3]原本是12。如果只通过1号城市中转(4->1->3),路程将缩短为11(e[4][1]+e[1][3]=5+6=11)。其实1号城市到3号城市也可以通过2号城市中转,使得1号到3号城市的路程缩短为5(e[1][2]+e[2][3]=2+3=5)。所以如果同时经过1号和2号两个城市中转的话,从4号城市到3号城市的路程会进一步缩短为10。通过这个的例子,我们发现每个顶点都有可能使得另外两个顶点之间的路程变短。好,下面我们将这个问题一般化。

 
        当任意两点之间不允许经过第三个点时,这些城市之间最短路程就是初始路程,如下。
       
 
 
假如现在只允许经过1号顶点,求任意两点之间的最短路程,应该如何求呢?只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环,代码实现如下。
for (int k = ; k <= n; ++k)
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
{
access[i][j] = min(access[i][j], access[i][k] + access[k][j]);
}
在只允许经过1号顶点的情况下,任意两点之间的最短路程更新为:
 
        通过上图我们发现:在只通过1号顶点中转的情况下,3号顶点到2号顶点(e[3][2])、4号顶点到2号顶点(e[4][2])以及4号顶点到3号顶点(e[4][3])的路程都变短了。
 
        接下来继续求在只允许经过1和2号两个顶点的情况下任意两点之间的最短路程。如何做呢?我们需要在只允许经过1号顶点时任意两点的最短路程的结果下,再判断如果经过2号顶点是否可以使得i号顶点到j号顶点之间的路程变得更短。即判断e[i][2]+e[2][j]是否比e[i][j]要小,代码实现为如下。
1 //经过1号顶点
2 for(i=1;i<=n;i++)
3 for(j=1;j<=n;j++)
4 if (e[i][j] > e[i][1]+e[1][j]) e[i][j]=e[i][1]+e[1][j];
5 //经过2号顶点
6 for(i=1;i<=n;i++)
7 for(j=1;j<=n;j++)
8 if (e[i][j] > e[i][2]+e[2][j]) e[i][j]=e[i][2]+e[2][j];
 
在只允许经过1和2号顶点的情况下,任意两点之间的最短路程更新为:
        通过上图得知,在相比只允许通过1号顶点进行中转的情况下,这里允许通过1和2号顶点进行中转,使得e[1][3]和e[4][3]的路程变得更短了。
 
        同理,继续在只允许经过1、2和3号顶点进行中转的情况下,求任意两点之间的最短路程。任意两点之间的最短路程更新为:
        最后允许通过所有顶点作为中转,任意两点之间最终的最短路程为:
        整个算法过程虽然说起来很麻烦,但是代码实现却非常简单,核心代码只有五行(大括号不算啦QAQ):
for (int k = ; k <= n; ++k)
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
{
access[i][j] = min(access[i][j], access[i][k] + access[k][j]);
}
这段代码的基本思想就是:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程。
 

另外需要注意的是:Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路。例如下面这个图就不存在1号顶点到3号顶点的最短路径。因为1->2->3->1->2->3->…->1->2->3这样路径中,每绕一次1->-2>3这样的环,最短路就会减少1,永远找不到最短路。其实如果一个图中带有“负权回路”那么这个图则没有最短路。

现在我们来看看一道例题

P1744 采购特价商品

这个题就是先把所有的坐标读进去,之后对于每一个可联通的商店我们算一次他们的距离存到图里,等到所有的数据都处理完一张图就诞生了,然后跑一遍Floyd,万事大吉

AC代码(一次过真的好久好久没出现了~嘤)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
struct emmmmmmm
{
int x, y;
} pos[];
int main()
{
int n, m, a, b, s, t;
double access[][];
memset(access, , sizeof(access));
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d%d", &pos[i].x, &pos[i].y);
scanf("%d", &m);
for (int i = ; i <= m; ++i)
{
scanf("%d%d", &a, &b);
access[a][b] = access[b][a] = (double)(sqrt(pow(pos[a].x - pos[b].x, ) + pow(pos[a].y - pos[b].y, )));
}
for (int k = ; k <= n; ++k)
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
{
access[i][j] = min(access[i][j], access[i][k] + access[k][j]);
}
scanf("%d%d", &s, &t);
printf("%.2lf", access[s][t]);
return ;
}

最后补一句

Floyd的时间复杂度是o (n^3),空间复杂度是o(n^2)(用的是邻接表)。

以及如果题目中数据范围<=5000,一般就是Floyd没跑了

n方过百万哦~(不过你别打算n^3过十万)

Floyd-蒟蒻也能看懂的弗洛伊德算法(当然我是蒟蒻)的更多相关文章

  1. Floyd算法-傻子也能看懂的弗洛伊德算法(转)

                暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程.          ...

  2. Floyd-傻子也能看懂的弗洛伊德算法(转)

                暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程.          ...

  3. 一个蒟蒻对FFT的理解(蒟蒻也能看懂的FFT)

    建议同学们先自学一下"复数(虚数)"的性质.运算等知识,不然看这篇文章有很大概率看不懂. 前言 作为一个典型的蒟蒻,别人的博客都看不懂,只好自己写一篇了. 膜拜机房大佬 HY 一. ...

  4. 萌新也能看懂的KMP算法

    前言 算法是什么?算法就是数学规律.怎么去总结和发现这个规律,就是理解算法的过程. KMP算法的本质是穷举法,而并不是去创造新的匹配逻辑. 以下将搜寻的字符串称为子串(part),以P表示.被搜寻的字 ...

  5. [转]看懂UML类图

    这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图所表达的含义和最终的代码 ...

  6. 看懂Oracle执行计划

    最近一直在跟Oracle打交道,从最初的一脸懵逼到现在的略有所知,也来总结一下自己最近所学,不定时更新ing- 一:什么是Oracle执行计划? 执行计划是一条查询语句在Oracle中的执行过程或访问 ...

  7. 一张图看懂ANSYS17.0 流体 新功能与改进

    一张图看懂ANSYS17.0 流体 新功能与改进   提交 我的留言 加载中 已留言   一张图看懂ANSYS17.0 流体 新功能与改进 原创2016-02-03ANSYS模拟在线模拟在线 模拟在线 ...

  8. 怎样看懂Oracle的执行计划

    怎样看懂Oracle的执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when ...

  9. 看懂SqlServer查询计划【转】

    原文链接:http://www.cnblogs.com/fish-li/archive/2011/06/06/2073626.html 开始 SQL Server 查找记录的方法 SQL Server ...

随机推荐

  1. int 与 Integer 的区别

    int和Integer的区别 Integer是int的包装类,int则是java的一种基本数据类型 Integer变量必须实例化后才能使用,而int变量不需要 Integer实际是对象的引用,当new ...

  2. Vue.js实现登录功能

    编写html,通过vue-resource.js库向后台提交数据 <!DOCTYPE html> <html lang="en"> <head> ...

  3. js基础复习点

    1.变量   var num=10;       var num1,num2,num3;   num1=10;   num2=20;   num3=30;       var num1=10,num2 ...

  4. 《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)

    DOM1级主要定义的是HTML和XML文档的底层结构.DOM2级和DOM3级在这个结构基础上引入了更多的交互能力,也支持更高级的XML特性.为此DOM2级和DOM3级分为了很多的模块(模块直接具有某种 ...

  5. java 线程池 ---- newSingleThreadExecutor()

    class MyThread implements Runnable{ private int index; public MyThread(int index){ this.index = inde ...

  6. Android项目实战(五十二):控制EditText输入内容大小写转换

    今日需求,EditText内容为一串字符串,要求将用户软键盘输入的小写字母在输入的时候自动转为大写字母,反之亦然. 效果如下: 第一次做该需求,原先想法: EditText.addTextChange ...

  7. Redis入门教程(一)

    一.NoSQL概述 1.什么是NoSQL NoSQL,泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯 ...

  8. oracle异地备份

    一.安装oracle客户端 右键以管理员身份运行 选择管理员 跳过软件更新 选择语言,默认中文 指定安装位置 检查当前环境 安装 二.使用exp命令备份 exp 用户名/密码@IP地址/数据库 own ...

  9. sql优化个人总结(全)

    sql优化总结--博客 第一次自己写博客,以后要坚持每掌握一个技能点,就要写一篇博客出来,做一个不满足于一个只会写if...else的程序员. 最近三个月入职了一家新的公司,做的是CRM系统,将公司多 ...

  10. Neutron vxlan network

    OpenStack 还支持 vxlan 和 gre 这两种 overlay network.   overlay network 是指建立在其他网络上的网络. 该网络中的节点可以看作通过虚拟(或逻辑) ...