Floyd 算法小结 

By Wine93 2013.11

1. Floyd算法简介

Floyd算法利用动态规划思想可以求出任意2点间的最短路径,时间复杂度为O(n^3),对于稠密图, 效率要高于执行|V|次Dijkstra算法.

核心代码如下:

for(k=1;k<=n;k++)

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

相关应用 : 有向图:①求任意2点间最短路径  ②求最小环(可判断负圈,检查dis[i][i])   ③求传递闭包

无向图:(无负权边): ①求任意2点间最短路径  ②求最小环

注意:对于有负权边的无向图,会出现很多意想不到的错误,请谨慎使用floyd。

2. 个人心得

对于floyd,我认为最重要的是理解k循环这层,每枚举一个k,代表下面代表的点对(i,j)之间的 最短路有可能会通过k这点而变小,也就是说在i到j的这条简单路径上插上k这个点,有可能会使路径长度变小。还有就是floyd求出来的最短路径肯定是简单路径(无向图)

关于可Floyd解的题其顶点数都比较小,根据这点会给我们一点暗示.

如果要输出floyd所求相关路径,我们可以记录mid[i][j](表示i到j这条路径中插入的点k),这样通过不断递归,就可以求出整条路径

3. Floyd算法的应用举例

(1) 求无向图最小环 

HDU 1599 find the mincost route

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<algorithm>
  4. using namespace std;
  5.  
  6. # define INF <<
  7. # define N
  8.  
  9. int mat[N][N],dis[N][N];
  10. int minloop;
  11.  
  12. void floyd(int n)
  13. {
  14. int i,j,k;
  15. for(k=;k<=n;k++)
  16. {
  17. for(i=;i<=n;i++)
  18. for(j=;j<=n;j++)
  19. if(i!=j&&i!=k&&j!=k&&dis[i][j]+mat[j][k]+mat[k][i]<minloop)
  20. minloop=dis[i][j]+mat[j][k]+mat[k][i];
  21. for(i=;i<=n;i++)
  22. for(j=;j<=n;j++)
  23. dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
  24. }
  25. }
  26.  
  27. void init(int n)
  28. {
  29. int i,j;
  30. minloop=INF;
  31. for(i=;i<=n;i++)
  32. for(j=;j<=n;j++)
  33. mat[i][j]=mat[j][i]=dis[i][j]=dis[j][i]=INF;
  34. }
  35.  
  36. int main()
  37. {
  38. // freopen("in.txt","r",stdin);
  39. int i,n,m,u,v,w;
  40. while(scanf("%d%d",&n,&m)!=EOF)
  41. {
  42. init(n);
  43. for(i=;i<=m;i++)
  44. {
  45. scanf("%d%d%d",&u,&v,&w);
  46. if(w<mat[u][v])
  47. mat[u][v]=mat[v][u]=dis[u][v]=dis[v][u]=w;
  48. }
  49. floyd(n);
  50. if(minloop==INF) printf("It's impossible.\n");
  51. else printf("%d\n",minloop);
  52. }
  53. return ;
  54. }

HDU 1599

POJ 1734 Sightseeing trip(需输出最小环)

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<vector>
  4. # include<algorithm>
  5. using namespace std;
  6.  
  7. # define pb push_back
  8. # define INF <<
  9. # define N
  10.  
  11. int mat[N][N],dis[N][N],mid[N][N],minloop;
  12. vector<int> vec;
  13.  
  14. void dfs(int l,int r)
  15. {
  16. if(mid[l][r]==-) return;
  17. dfs(l,mid[l][r]);
  18. vec.pb(mid[l][r]);
  19. dfs(mid[l][r],r);
  20. }
  21.  
  22. void floyd(int n)
  23. {
  24. int i,j,k;
  25. for(k=;k<=n;k++)
  26. {
  27. for(i=;i<k;i++)
  28. for(j=i+;j<k;j++)
  29. {
  30. if(dis[i][j]+mat[j][k]+mat[k][i]<minloop)
  31. {
  32. minloop=dis[i][j]+mat[j][k]+mat[k][i];
  33. vec.clear();
  34. vec.pb(i);
  35. dfs(i,j);
  36. vec.pb(j);
  37. vec.pb(k);
  38. }
  39. }
  40. for(i=;i<=n;i++)
  41. for(j=;j<=n;j++)
  42. {
  43. if(dis[i][k]+dis[k][j]<dis[i][j])
  44. {
  45. dis[i][j]=dis[i][k]+dis[k][j];
  46. mid[i][j]=k;
  47. }
  48. }
  49. }
  50. }
  51.  
  52. void init(int n)
  53. {
  54. int i,j;
  55. minloop=INF;
  56. for(i=;i<=n;i++)
  57. for(j=;j<=n;j++)
  58. mat[i][j]=dis[i][j]=INF,mid[i][j]=-;
  59. vec.clear();
  60. }
  61.  
  62. int main()
  63. {
  64. //freopen("in.txt","r",stdin);
  65. int i,j,n,m,u,v,w;
  66. while(scanf("%d%d",&n,&m)!=EOF)
  67. {
  68. init(n);
  69. for(i=;i<=m;i++)
  70. {
  71. scanf("%d%d%d",&u,&v,&w);
  72. if(w<mat[u][v])
  73. dis[u][v]=dis[v][u]=mat[u][v]=mat[v][u]=w;
  74. }
  75. floyd(n);
  76. if(minloop==INF)
  77. {
  78. printf("No solution.\n");
  79. continue;
  80. }
  81. printf("%d",vec[]);
  82. for(i=;i<vec.size();i++)
  83. printf(" %d",vec[i]);
  84. printf("\n");
  85. }
  86. return ;
  87. }

POJ 1734

相关证明理解请参考下面博客,讲解的非常好:

http://www.kaixinwenda.com/article-aclion-8074848.html

(2)判断有向图是否有正环

POJ 2240 Arbitrage

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<string>
  4. # include<map>
  5. # include<algorithm>
  6. using namespace std;
  7.  
  8. # define N
  9. double dis[N][N];
  10.  
  11. void floyd(int n)
  12. {
  13. int i,j,k;
  14. for(k=;k<=n;k++)
  15. for(i=;i<=n;i++)
  16. for(j=;j<=n;j++)
  17. dis[i][j]=max(dis[i][j],dis[i][k]*dis[k][j]);
  18. }
  19.  
  20. void init(int n)
  21. {
  22. int i,j;
  23. for(i=;i<=n;i++)
  24. for(j=;j<=n;j++)
  25. dis[i][j]=(i==j)?:;
  26. }
  27.  
  28. int main()
  29. {
  30. // freopen("in.txt","r",stdin);
  31. map<string,int> Hash;
  32. int i,n,m,num,flag,cas=,u,v;
  33. char s1[N],s2[N];
  34. double d;
  35. while(scanf("%d",&n)!=EOF&&n)
  36. {
  37. Hash.clear();
  38. flag=num=;
  39. init(n);
  40. for(i=;i<=n;i++)
  41. {
  42. scanf("%s",s1);
  43. Hash[s1]=++num;
  44. }
  45. scanf("%d",&m);
  46. for(i=;i<=m;i++)
  47. {
  48. scanf("%s %lf %s",s1,&d,s2);
  49. u=Hash[s1];
  50. v=Hash[s2];
  51. dis[u][v]=max(dis[u][v],d);
  52. }
  53. floyd(n);
  54. printf("Case %d: ",cas++);
  55. for(i=;i<=n;i++)
  56. if(dis[i][i]>1.0)
  57. {
  58. flag=;
  59. break;
  60. }
  61. if(flag) printf("Yes\n");
  62. else printf("No\n");
  63. }
  64. return ;
  65. }

POJ 2240

(3)传递闭包

POJ 3660 Cow Contest

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<algorithm>
  4. using namespace std;
  5.  
  6. # define N
  7. int f[N][N],beat[N],win[N];
  8.  
  9. void floyd(int n)
  10. {
  11. int i,j,k;
  12. for(k=;k<=n;k++)
  13. for(i=;i<=n;i++)
  14. for(j=;j<=n;j++)
  15. f[i][j]|=(f[i][k]&&f[k][j]);
  16. }
  17.  
  18. int main()
  19. {
  20. int i,j,n,m,u,v,ans;
  21. while(scanf("%d%d",&n,&m)!=EOF)
  22. {
  23. ans=;
  24. memset(beat,,sizeof(beat));
  25. memset(win,,sizeof(win));
  26. memset(f,,sizeof(f));
  27. for(i=;i<=m;i++)
  28. {
  29. scanf("%d%d",&u,&v);
  30. f[u][v]=;
  31. }
  32. floyd(n);
  33. for(i=;i<=n;i++)
  34. {
  35. for(j=;j<=n;j++)
  36. if(f[j][i]) //j beat i
  37. {
  38. win[j]++;
  39. beat[i]++;
  40. }
  41. }
  42. for(i=;i<=n;i++)
  43. if(win[i]+beat[i]==n-)
  44. ans++;
  45. printf("%d\n",ans);
  46. }
  47. return ;
  48. }

POJ 3660

(4)好题推荐(独立完成)

HDU 3631 Shortest Path    //深入理解floyd

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<algorithm>
  4. using namespace std;
  5.  
  6. # define INF <<
  7. # define N
  8.  
  9. int n,m,q;
  10. int dis[N][N];
  11. int mark[N];
  12.  
  13. void floyd(int k)
  14. {
  15. int i,j;
  16. for(i=;i<n;i++)
  17. for(j=;j<n;j++)
  18. dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
  19. }
  20.  
  21. void init(int n)
  22. {
  23. int i,j;
  24. memset(mark,,sizeof(mark));
  25. for(i=;i<n;i++)
  26. for(j=;j<n;j++)
  27. dis[i][j]=(i==j)?:INF;
  28. }
  29.  
  30. int main()
  31. {
  32. //freopen("in.txt","r",stdin);
  33. int i,j,u,v,w,op,cas=;
  34. while(scanf("%d%d%d",&n,&m,&q)!=EOF&&(n+m+q))
  35. {
  36. init(n);
  37. for(i=;i<=m;i++)
  38. {
  39. scanf("%d%d%d",&u,&v,&w);
  40. dis[u][v]=min(dis[u][v],w);
  41. }
  42. if(cas>) printf("\n");
  43. printf("Case %d:\n",cas++);
  44. for(i=;i<=q;i++)
  45. {
  46. scanf("%d",&op);
  47. if(op==)
  48. {
  49. scanf("%d",&u);
  50. if(mark[u])
  51. printf("ERROR! At point %d\n",u);
  52. else
  53. {
  54. mark[u]=;
  55. floyd(u);
  56. }
  57. }
  58. else
  59. {
  60. scanf("%d%d",&u,&v);
  61. if(!mark[u]||!mark[v])
  62. printf("ERROR! At path %d to %d\n",u,v);
  63. else if(dis[u][v]==INF)
  64. printf("No such path\n");
  65. else
  66. printf("%d\n",dis[u][v]);
  67. }
  68. }
  69. }
  70. return ;
  71. }

HDU 3631

HDU 4034 Graph               //深入理解floyd ,思维锻炼

  1. # include<cstdio>
  2. # include<cstring>
  3. # include<algorithm>
  4. using namespace std;
  5.  
  6. # define N
  7. int dis[N][N];
  8. int vis[N][N];
  9.  
  10. int floyd(int n)
  11. {
  12. int i,j,k,ans=n*(n-);
  13. memset(vis,,sizeof(vis));
  14. for(k=;k<=n;k++)
  15. for(i=;i<=n;i++)
  16. for(j=;j<=n;j++)
  17. {
  18. if(dis[i][k]+dis[k][j]<dis[i][j])
  19. return -;
  20. if(!vis[i][j]&&i!=k&&j!=k&&i!=j&&dis[i][k]+dis[k][j]==dis[i][j])
  21. {
  22. ans--;
  23. vis[i][j]=;
  24. }
  25. }
  26. return ans;
  27. }
  28.  
  29. int main()
  30. {
  31. //freopen("in.txt","r",stdin);
  32. int cas,T,i,j,n,ans;
  33. scanf("%d",&T);
  34. for(cas=;cas<=T;cas++)
  35. {
  36. scanf("%d",&n);
  37. for(i=;i<=n;i++)
  38. for(j=;j<=n;j++)
  39. scanf("%d",&dis[i][j]);
  40. printf("Case %d: ",cas);
  41. ans=floyd(n);
  42. if(ans==-)
  43. printf("impossible\n");
  44. else
  45. printf("%d\n",ans);
  46. }
  47. return ;
  48. }

HDU 4034

4. 个人总结

Floyd算法有很多其他的应用,需要不断的积累,但是我相信只要能理解好floyd的DP思想(每个k点插入或者不插入相关路径),很多问题多能迎刃而解.

附录:关于Floyd判断环的可行性

注:该附录未经严格验证,请读者认真思考 

[图论]Floyd 算法小结的更多相关文章

  1. floyd算法小结

    floyd算法是被大家熟知的最短路算法之一,利用动态规划的思想,f[i][j]记录i到j之间的最短距离,时间复杂度为O(n^3),虽然时间复杂度较高,但是由于可以处理其他相似的问题,有着广泛的应用,这 ...

  2. [图论]Dijkstra 算法小结

    Dijkstra 算法小结  By Wine93 2013.11 1. Dijkstra 算法相关介绍 算法阐述:Dijkstra是解决单源最短路径的算法,它可以在O(n^2)内计算出源点(s)到图中 ...

  3. 图论·Floyd算法·HDU2544&1874 (伪)2066

    在看到1874的题时,第一反应是用上一篇的并查集方法,后来查了一下是要用Floyd做,所以就去查Floyd算法的资料. 即插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法. 核心代码:  ma ...

  4. 图论——Floyd算法拓展及其动规本质

    一.Floyd算法本质 首先,关于Floyd算法: Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法.算法的单个执行将找到所有顶点对之间的最短路径 ...

  5. 【uva 10048】Audiophobia(图论--Floyd算法)

    题意:有一个N点M边的无向带权图,边权表示路径上的噪声值.有Q个询问,输出 x,y 两点间的最大噪声值最小的路径的该值.(N≤100,M≤1000,Q≤10000) 解法:N值小,且问多对点之间的路径 ...

  6. 图论(floyd算法):NOI2007 社交网络

    [NOI2007] 社交网络 ★★   输入文件:network1.in   输出文件:network1.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 在社交网络( ...

  7. 图论之最短路径floyd算法

    Floyd算法是图论中经典的多源最短路径算法,即求任意两点之间的最短路径. 它可采用动态规划思想,因为它满足最优子结构性质,即最短路径序列的子序列也是最短路径. 举例说明最优子结构性质,上图中1号到5 ...

  8. 图论篇3——最短路径 Dijkstra算法、Floyd算法

    最短路径 问题背景:地图上有很多个城市,已知各城市之间距离(或者是所需时间,后面都用距离了),一般问题无外乎就是以下几个: 从某城市到其余所有城市的最短距离[单源最短路径] 所有城市之间相互的最短距离 ...

  9. 图论算法(二)最短路算法:Floyd算法!

    最短路算法(一) 最短路算法有三种形态:Floyd算法,Shortset Path Fast Algorithm(SPFA)算法,Dijkstra算法. 我个人打算分三次把这三个算法介绍完. (毕竟写 ...

随机推荐

  1. python中关闭文件

    1.关闭文件,通过f.write把内容写入文件会覆盖之前文件中的内容

  2. java下载网络图片

    import java.io.DataInputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IO ...

  3. C语言实现进制转换

    #include<stdio.h> int main() {     char ku[16]={'0','1','2','3','4','5','6','7','8','9','A','B ...

  4. PHP可变长函数方法介绍

    1.三个重要函数 func_num_args()  返回实参个数 func_get_arg(i)    返回某个实参的值       func_get_args()        以数组的形式返回实参 ...

  5. 一个简单的excel文件上传到数据库方法

    因为以前项目中有用到过Excel导入,所以整理了一下,这是一个导入Excel数据到数据库的方法 注意:需要导入poi jar包 代码清单 /** * Excel 导入 * @param mapping ...

  6. [Hadoop入门] - 2 ubuntu安装与配置 hadoop安装与配置

    ubuntu安装(这里我就不一一捉图了,只引用一个网址, 相信大家能力) ubuntu安装参考教程:  http://jingyan.baidu.com/article/14bd256e0ca52eb ...

  7. 为ASP.NET MVC应用添加自定义路由

    这里,我们将学习如何给asp.net mvc应用添加自定义路由.用自定义路由来修改默认路由表. 对一些简单的asp.net mvc应用,默认的路由表就已经足够了.但是,当你需要创建特殊的路由时,就需要 ...

  8. 在其他页面调用 Discuz 7.2 BBS 论坛会员登录信息

    require_once './bbs/include/common.inc.php'; $discuz_uid 是用户ID $_DSESSION是用户所有信息

  9. limit 百万级数据分页优化方法

    mysql教程 这个数据库教程绝对是适合dba级的高手去玩的,一般做一点1万 篇新闻的小型系统怎么写都可以,用xx框架可以实现快速开发.可是数据量到了10万,百万至千万,他的性能还能那么高吗? 一点小 ...

  10. [开发笔记]-VS2012打开解决方案崩溃或点击项目崩溃

    下午在使用VS2012建立Service服务项目时,只要一切换到设计视图页面中,VS就崩溃重启,从网上找了一种方法来解决,测试可行.但导致该问题的原因未知. 解决方案: 步骤1:开始-->所有程 ...