floyd原理以及求最小环

floyd这个东西学会了好久了,但是原理总是忘记,或者说没有真正的明白,这里在说一下。

我们要求的是任意的 i,j 之间的最短路径,用动态规划的思想来解决就是f[i,j,k]表示i到j中间节点不超过k的最短路径,那么分两种情况讨论:

case1:经过k,如果经过k,很显然f[i,j,k]=f[i,k,k-1]+f[k,j,k-1]; 由动态规划的一些性质可以知道,这样是无后效性的;

case2:不经过k,那么很简单,f[i,j,k]=f[i,j,k-1];

发现这两个方程中至于k-1有关,这样便可以省去一维空间,变成f[i,j]=max(f[i,j],f[i,k]+f[k,j]);

至于k,只需要迭代就可以了。

————————————————————————————————————————————————————————————————

floyd求最小环:

先来贴个代码:

 1 int mincircle = infinity;
 2 Dist = Graph;
 3 for(int k=0;k<nVertex;++k){
 4     //新增部分:
 5     for(int i=0;i<k;++i)
 6         for(int j=0;j<i;++j)
 7             mincircle = min(mincircle,Dist[i][j]+Graph[j][k]+Graph[k][i]);
 8     //通常的 floyd 部分:
 9     for(int i=0;i<nVertex;++i)
10         for(int j=0;j<i;++j){
11             int temp = Dist[i][k] + Disk[k][j];
12             if(temp < Dist[i][j])
13                 Dist[i][j] = Dist[j][i] = temp;
14         }
15 }

大家可以先仔细看看这代码

 

 

 

 

发现了吗?只是在普通的floyd基础上又进行了了一个找环操作。相信大家仔细琢磨能琢磨出个大概意思,不顾我要在这里解释2个难理解的地方

1、为什么新增部分放在第K次最短路前面

【最小环的一个算法】令e(u,v)表示u和v之间的连边,再令min(u,v)表示,删除u和v之间的连边之后,u和v之间的最短路最小环则是min(u,v) + e(u,v)

Floyd中的k用来作为每节点进行最短路的更新min(u,v)路过K点,由于k是0~n,如果我们按照k值作为环节点的最大值,则可以取环【名叫第k层环】

dist存两点间的最短距离,g存放原图距离那么第k环的最小环

min= g[l~k]+g[k~r]+dist[l][r] 其中0<l<r<k

其中对dist[l][r]的要求是dist没有经过点值大于k的点的优化。

【反例】如果求第k层环的最小环时 dist有进过k点优化过,那么可能产生dist[l][r]=g[l][k]+g[k][r]

那么结果就变成:min=2*(g[l][k]+g[k][r]) 很明显这只是对一条路径的来回走动,而非环所以第k层环的最小

所以k层环应该要在求 dist有路由k点之前求出!

【结论】k层环的最小环 = g[l~k] + g[k~r] + dist[l][r] {0<l<r<k(dist为k-1层环时候更新的最短路)

2、为什么不能在原数组上直接操作而要两个数组?(一般的floyd都在一个数组上操作)

原因很简单,和第一个问题一样,如果在原数组上操作,就会有dist在前面被优化过,会产生1中的【反例】

posted @ 2013-12-20 00:23  Chellyutaha  阅读(583)  评论(0编辑  收藏  举报