本文转自这里

  最小环:从一个点出发,经过一条简单路径回到起点成为环.图的最小环就是所有环中长度最小的.

  怎样求最小环呢?

  1传统的解决方法(dijkstra):
        任意一个最小环环的权值,我们都可以看成两个有边相连的结点i、j的直接距离加上i、j间不包含边(边i->j)的最短路径。求最短路径我们第一个想到的就Dijkstra算法。而Dijkstra所求的是一个点到所有点的最短距离。用Dijkstra所求的i、j的最短距离一定是i、j的直接距离(如果i,j连通),所以我们需要先将i、j的边从图中删除(若i,j不连通,则不用删除),再用Dijkstra求新图中i、j的最短距离即可。所以我们每次在图中选取一条边,把它从图中删掉.然后对删掉的那条边所对应的2点进行Dijkstra,也就是m次Dijkstra。

  2.floyd求最小环:

抛开Dijkstra算法,进而我们想到用Floyd算法。我们知道,Floyd算法在进行时会不断更新矩阵dist(k)。设dist[k,i,j]表示从结点i到结点j且满足所有中间结点,它们均属于集合{1,2,⋯ ,k}的一条最短路径的权。其中dist[0,i,j ]即为初始状态i到j的直接距离。对于一个给定的赋权有向图, 求出其中权值和最小的一个环。我们可以将任意一个环化成如下形式:u->k->v ->(x1-> x2-> ⋯ xm1)-> u(u与k、k与v都是直接相连的),其中v ->(x1-> 2-> ⋯ m)-> u是指v到u不经过k的一种路径。

在u,k,v确定的情况下,要使环权值最小, 则要求 (x1一>x2->⋯一>xm)->u路径权值最小.即要求其为v到u不经过k的最短路径,则这个经过u,k,v的环的最短路径就是:[v到u不包含k的最短距离]+dist[O,u,k]+dist[O,k,v]。我们用Floyd只能求出任意2点间满足中间结点均属于集合{1,2,⋯ ,k}的最短路径,可是我们如何求出v到u不包含k的最短距离呢?
         现在我们给k加一个限制条件:k为当前环中的序号最大的节点(简称最大点)。因为k是最大点,所以当前环中没有任何一个点≥k,即所有点都<k。因为v->(x1->x2->......xm)->u属于当前环,所以x1,x2,⋯ ,xm<k,即x1,x2.⋯。xm≤k一1。这样,v到u的最短距离就可以表示成dist[k一1 ,u,v]。dist[k一1,v,u]表示的是从v到u且满足所有中间结点均属于集合{1,2,⋯ ,k一1}的一条最短路径的权。接下来,我们就可以求出v到u不包含k的最短距离了。这里只是要求不包含k,而上述方法用的是dist[k一1,v,u],求出的路径永远不会包含k+l,k+2,⋯ 。万一所求的最小环中包含k+1,k+2,⋯ 怎么办呢?的确,如果最小环中包含比k大的节点,在当前u,k,v所求出的环显然不是那个最小环。然而我们知道,这个最小环中必定有一个最大点kO,也就是说,虽然当前k没有求出我们所需要的最小环,但是当我们从k做到kO的时候,这个环上的所有点都小于kO了.也就是说在k=kO时一定能求出这个最小环。我们用一个实例来说明:假设最小环为1—3—4—5—6—2—1。的确,在u=l,v=4,k=3时,k<6,dist[3,4,1]的确求出的不是4—5—6—2—1这个环,但是,当u=4,v=6,k=5或u=5,v=2,k=6时,dist[k,v,u]表示的都是这条最短路径.所以我们在Floyd以后,只要枚举u.v,k三个变量即可求出最小环。时间复杂度为O(n3)。我们可以发现,Floyd和最后枚举u,v,k三个变量求最小环的过程都是u,v,k三个变量,所以我们可以将其合并。这样,我们在k变量变化的同时,也就是进行Floyd算法的同时,寻找最大点为k的最小环。

POJ 1734  

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define _Clr(x, y) memset(x, y, sizeof(x))
  5. #define INF 0xfffffff
  6. #define N 110
  7. using namespace std;
  8.  
  9. int mat[N][N], dist[N][N];
  10. int next[N][N]; // next[i][j]表示i到j经历的第一个点。
  11. int path[N];
  12. int cnt, n;
  13.  
  14. void Floyd()
  15. {
  16. int mins=INF;
  17. for(int k=; k<=n; k++)
  18. {
  19. for(int i=; i<k; i++)
  20. for(int j=i+; j<k; j++)
  21. {
  22. int tmp = dist[i][j]+mat[i][k]+mat[k][j];
  23. if(tmp < mins)// 更新最小环的权值
  24. {
  25. mins = tmp;
  26. cnt=;
  27. int p = i;
  28. while(p!=j) // 记录最小环的路径
  29. {
  30. path[cnt++] = p;
  31. p = next[p][j];
  32. }
  33. path[cnt++] = j;
  34. path[cnt++] = k;
  35. }
  36. }
  37. for(int i=; i<=n; i++)
  38. for(int j=; j<=n; j++)
  39. {
  40. if(dist[i][k]+dist[k][j] < dist[i][j])
  41. {
  42. dist[i][j] = dist[i][k] + dist[k][j];
  43. next[i][j] = next[i][k];
  44. }
  45. }
  46. }
  47. if(mins==INF)
  48. puts("No solution.");
  49. else
  50. {
  51. for(int i=; i<cnt; i++)
  52. printf("%d%s", path[i], i==cnt- ? "\n":" ");
  53. }
  54. }
  55.  
  56. void Init()
  57. {
  58. for(int i=; i<=n; i++)
  59. for(int j=; j<=n; j++)
  60. {
  61. mat[i][j] = dist[i][j] = INF;
  62. next[i][j] = j;
  63. }
  64. }
  65. int main()
  66. {
  67. int m, a, b, c;
  68. while(~scanf("%d%d", &n, &m))
  69. {
  70. Init();
  71. while(m--)
  72. {
  73. scanf("%d%d%d", &a, &b, &c);
  74. if(c < mat[a][b])
  75. {
  76. mat[a][b] = mat[b][a] = c;
  77. dist[a][b] = dist[b][a] = c;
  78. }
  79. }
  80. Floyd();
  81. }
  82. return ;
  83. }

Floyd最小环的更多相关文章

  1. hdoj 1599 find the mincost route【floyd+最小环】

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  2. POJ 1734.Sightseeing trip (Floyd 最小环)

    Floyd 最小环模板题 code /* floyd最小环,记录路径,时间复杂度O(n^3) 不能处理负环 */ #include <iostream> #include <cstr ...

  3. HDU - 6080 :度度熊保护村庄 (凸包,floyd最小环)(VJ1900题达成)

    pro:二维平面上,给定N个村庄.M个士兵驻守,把村庄围住,现在我们想留下更多的士兵休息,使得剩下的士兵任然满足围住村庄.N,M<500: sol:即是要找一个最小的环,环把村庄围住. 由于是环 ...

  4. HDU1599(Floyd最小环)

    Floyd最小环理解+模板: https://www.cnblogs.com/DF-yimeng/p/8858184.html 除了上述博文里写的,我再补充几点我的理解. 1.为什么先枚举ij求经过i ...

  5. D. Shortest Cycle(floyd最小环)

    D. Shortest Cycle time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  6. floyd最小环&&模板

    floyd的核心代码: ;k<=n;k++){ ;i<=n;i++){ ;j<=n;j++){ dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j] ...

  7. Vijos1046观光旅游[floyd 最小环]

    背景 湖南师大附中成为百年名校之后,每年要接待大批的游客前来参观.学校认为大力发展旅游业,可以带来一笔可观的收入. 描述 学校里面有N个景点.两个景点之间可能直接有道路相连,用Dist[I,J]表示它 ...

  8. HD1599 find the mincost route(floyd + 最小环)

    题目链接 题意:求最小环 第一反应时floyd判断,但是涉及到最少3个点,然后就不会了,又想的是 双联通分量,这个不知道为什么不对. Floyd 判断 最小环 #include <iostrea ...

  9. bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)

    1027: [JSOI2007]合金 Time Limit: 4 Sec  Memory Limit: 162 MBSubmit: 2970  Solved: 787[Submit][Status][ ...

随机推荐

  1. Ghost克隆软件

    克隆软件Ghost初级使用教程 一.什么是Ghost ? Ghost(幽灵)软件是美国赛门铁克公司推出的一款出色的硬盘备份还原工具,可以实现FAT16.FAT32.NTFS.OS2等多种硬盘分区格式的 ...

  2. Guava API学习之Optional 判断对象是否为null

    java.lang.NullPointerException,只要敢自称Java程序员,那对这个异常就再熟悉不过了.为了防止抛出这个异常,我们经常会写出这样的代码: Person person = p ...

  3. angular ng-bind-html 对src路径失效 解决方案

    json内容 ;<img src="/newsfile/1506271512489.jpg" width="600" height="450&q ...

  4. Ubuntu 配置swftools(Ubuntu14.04)

    1.下载文件 wget http://swftools.org/swftools-0.9.0.tar.gz .tar.gz wget http://www.ijg.org/files/jpegsrc. ...

  5. C语言初学 计算二元一次方程的问题

    #include<stdio.h> #include<math.h> int main() { double a,b,c,disc,x1,x2; scanf("%lf ...

  6. 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接

    由于项目中必须得用JDK6来作为Java环境,于是连接SQLServer时出现了com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安 ...

  7. 关于自动编译iOS工程,生成app及ipa文件的方法-备

    文章地址. 1.所需语句(可直接在命令行中执行) xcodebuild -configuration Release        进入所在工程的根目录文件夹,执行上面的语句,即可开始自动使用rele ...

  8. KEIL 伪指令

    //为了大家查找方便,命令按字母排序:0.ALTNAME 功能: 这一伪指令用来自定义名字,以替换源程序中原来的保留字,替换的保留字均可等效地用于子程序中. 格式: ALTNAME 保留字 自定义名 ...

  9. MySQL的SQL_CALC_FOUND_ROWS真的很慢么?

    分页程序一般由两条SQL组成: SELECT COUNT(*) FROM ... WHERE .... SELECT ... FROM ... WHERE LIMIT ... 如果使用SQL_CALC ...

  10. 【转】NPAPI 插件无法在 Chrome 42 版及更高版本上正常运行

    原文网址:https://support.google.com/chrome/answer/6213033 NPAPI 插件无法在 Chrome 42 版及更高版本上正常运行 您可以利用插件在浏览器中 ...