floyd可以在O(n3)的时间复杂度,O(n2)的空间复杂度下求解正权图中任意两点间的最短路长度.

本质是动态规划.

定义f[k][i][j]表示从i出发,途中只允许经过编号小于等于k的点时的最短路.(i,j可以大于k但i到j的路径上的其他点必须编号小于等于k).

转移时从第k层的DP数组f[k][][]求解第k+1层的DP数组f[k+1][i][j].

不妨将f[k+1][][]全部初始化为inf(一个足够大的值,可以是1000000,0x3f3f3f3f,或者其他的东西).

一条路径如果保证中转的点编号小于等于k,那么一定也满足经过的点的编号小于等于k+1.于是可以先将上一层的dp数组直接复制到第k+1层,f[k+1][i][j]=f[k][i][j].

接下来考虑经过了第k+1个点作为中转点的最短路.我们枚举(i,j),i!=k+1,j!=k+1,然后令f[k+1][i][j]=min(f[k+1][i][j],f[k][i][k+1]+f[k][k+1][j]).

直接这么写的空间复杂度是O(n3),接下来我们把空间压到O(n2).i,j这两维都是压不掉的,所以我们把k这一维压掉.

f[i][j]现在存的是f[k][i][j].接下来我们把f[i][j]进行更新使得它里面的数值变为f[k+1][i][j].

注意正权图的最短路中显然没有环,那么f[k][k+1][i]和f[k][k][i]的数值是相等的,f[k][i][k+1]和f[k+1][i][k+1]的数值也是相等的.(起点/终点当中有一个点是k+1,那么在中转点中允许经过k+1不会让这个最短路变短).也就是说,从f[k][][]转移到f[k+1][][]的时候,第k+1行和第k+1列都是不需要更新的.

而f[k+1][i][j]=min(f[k+1][i][j],f[k][i][k+1]+f[k][k+1][j]).用到的正是f[k][][]的第k+1行和第k+1列.

那么我们只需用f[i][j]的第k+1行第k+1列去更新其他行列的位置,就完成了f[k][i][j]到f[k+1][i][j]的转移.

于是我们得到了floyd算法的经典实现:

for(int k=1;k<=n;++k)//n为图的点数
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
f[i][j]=min(f[i][j],f[i][k]+f[k][j])

另一种实现:

for(int k=0;k<n;++k)
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
if(i!=k&&j!=k&&i!=j)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);

不判断i,j,k是否相等也不会影响结果的正确性.当然i,j,k出现相等时这样的转移没有什么实际意义.

如何初始化?如果i到j有一条长度为w的边那么我们把f[i][j]赋值为w.如果i到j没有边我们将f[i][j]赋值为inf,认为从i到j有一条长度大到不影响结果的边(inf是一个对于数据范围来说足够大的值.当用int存储f[i][j]的时候inf常用0x3f3f3f3f.如果将inf取值为0x7f7f7f7f,将容易导致int加法溢出).

f[i][i]如何初始化?实际上,将f[i][i]初始化为任何值都不会影响floyd算法的正确性.为了统一性起见,一般把f[i][i]初始化为0.从i出发不需要走任何边就能到达i.

计算从i到j的长度等于最短路的路径条数g[i][j]?bzoj1491[NOI2007]社交网络

定义g[k][i][j]表示从i到j,允许经过编号小于等于k的点,长度等于f[k][i][j]的路径条数,转移的时候需要考虑f[k][i][j]的数值是否等于f[k+1][i][j]然后进行讨论.g[k][i][j]也可以变成二维数组g[i][j].

dp的顺序一定是从1到n吗?luogu2966[USACO09DEC]牛收费路径

实际上我们枚举k的顺序可以改变,例如随便取一个1到n的排列,定义f[k][i][j]为允许以排列中前k个点作为中转点时i到j的最短路.对于Tolls这个题就是按照点权顺序.

求有向图中的最小环?(一个边权和最小的回路)vijos1423最佳路线

环上至少有两个点.枚举i,j,用f[i][j]+f[j][i]更新答案即可.如果必须经过点1,那么用f[1][i]+f[i][1]更新答案.(必须经过点1的时候,其实只需在原图和所有边反向的图上各从1出发跑一遍dijkstra)

求无向图最小环?(不允许重复经过同一条边,例如从1走到2再从2走回1不是一个环)

不能直接套用有向图最小环算法.

由于无向图中的最小环至少包含三个点,所以我们可以O(n^3)枚举三个点:首先枚举环中编号最大的点k然后枚举和k相邻的两个点i,j(要求k,i之间,k,j之间必须有边).那么i和j之间怎样连接?因为我们需要让k成为编号最大的点,那么i和j之间的路径长度只能是f[k][i][j].因此我们在floyd枚举的过程中更新到f[k][i][j]时统计以k作为编号最大的点的最小环.

floyd最短路的更多相关文章

  1. Floyd最短路算法

    Floyd最短路算法 ----转自啊哈磊[坐在马桶上看算法]算法6:只有五行的Floyd最短路算法 暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计 ...

  2. 【啊哈!算法】算法6:只有五行的Floyd最短路算法

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

  3. 【坐在马桶上看算法】算法6:只有五行的Floyd最短路算法

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

  4. BZOJ1491: [NOI2007]社交网络(Floyd 最短路计数)

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2343  Solved: 1266[Submit][Status][Discuss] Descripti ...

  5. Wikioi 1020 孪生蜘蛛 Label:Floyd最短路

    题目描述 Description 在G城保卫战中,超级孪生蜘蛛Phantom001和Phantom002作为第三层防卫被派往守护内城南端一带极为隐秘的通道. 根据防护中心的消息,敌方已经有一只特种飞蛾 ...

  6. FZU2090 旅行社的烦恼 巧妙floyd 最短路

    分析:floyd看似很好理解,实际上是状态转移,具体的解释参照这里 http://www.cnblogs.com/chenying99/p/3932877.html 深入理解了floyd后,这个题就可 ...

  7. 只有五行的Floyd最短路算法

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

  8. 仅仅有五行的Floyd最短路算法

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

  9. BZOJ 1491 社交网络 Floyd 最短路的数目

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1491 题目大意: 见链接 思路: 直接用floyd算法求最短路,同时更新最短路的数目即 ...

随机推荐

  1. combobox添加复选框

    问题: 需求提出要做一个下拉框可以多选的 解决方案: //机构树 function initOrgTree() { $('#reportOrg').combobox({ width: 200, edi ...

  2. c++ 时间函数和结构化数据

     time和localtime  数据结构概念  struct关键字  认识数据结构  自定义结构 例:获取当前系统日期和时间;(代码例子) 一.函数: time 函数time()返回的是当 ...

  3. Deep Learning 教程翻译

    Deep Learning 教程翻译 非常激动地宣告,Stanford 教授 Andrew Ng 的 Deep Learning 教程,于今日,2013年4月8日,全部翻译成中文.这是中国屌丝军团,从 ...

  4. P3374 【模板】树状数组 1(单点增减,区间求和)

    P3374 [模板]树状数组 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示 ...

  5. Win SERVER 2008 许可证激活失败,系统重启问题

    服务器系统win server2008 R2 SP1,频繁重启,查看日志 有显示 许可证激活(slui.exe)失败,错误代码如下:0x800401F9 和 Windows 许可证激活失败.错误 0x ...

  6. PHP 行为测试工具 Codeception (介绍)

    原文地址:https://phphub.org/topics/25 Codeception 简介 Codeception 简单来说, 分为以下几种测试 Acceptance Tests 验收测试 Fu ...

  7. kali安装后相关软件的配置

    更新软件apt-get updateapt-get upgrade安装输入法apt-get install ibus-pinyin apt-get install netspeed安装GNOMEapt ...

  8. VS2008 "无法找到资源编译器dll 请确保路径正确"

    系统环境:windows 8.1 企业版 x64 (装有 .NET 2.0 / 3.5 / 4.0 /  4.5) 安装前确认系统已安装 .NET 2.0 / 3.5 .在安装时,最好是默认安装,并且 ...

  9. [转]git学习------>git-rev-parse命令初识

    git学习------>git-rev-parse命令初识 2017年06月13日 10:04:13 阅读数:2172 一.准备工作 第一步:在d盘git test目录下,新建工作区根目录dem ...

  10. 在Unity中使用带碰撞体的TiledMap

    虽然最近Unity2018版本推出了自己的瓦片地图,但是这个瓦片地图有点BUG,在场景内把瓦片地图铺好做成预制体,动态生成的时候居然丢失了碰撞体,于是我决定还是使用Tiled软件绘制地图并使用Tile ...