floyd求最小环

Floyd 算法保证了最外层循环到 k 时所有顶点间已求得以 0…k-1 为中间点的最短路径。

一个环至少有3个顶点,设某环编号最大的顶点为 L ,在环中直接与之相连的两个顶点编号分别为 M 和 N (M,N < L),

则最大编号为 L 的最小环长度即为 Graph(M,L) + Graph(N,L) + Dist(M,N) ,  (Graph是原图)

其中 Dist(M,N) 表示以 0…L-1 号顶点为中间点时的最短路径,刚好符合 Floyd 算法最外层循环到 k=L 时的情况,则此时对 M 和 N 循环所有编号小于 L 的顶点组合即可找到最大编号为 L 的最小环。

再经过最外层 k 的循环,即可找到整个图的最小环。

 

模板:

1.只求值:

for(int k=1;k<=n; k++){
    //新增部分:
    for(int i=1;i<k; i++)
        for(int j=i+1;j<k; j++)
            mincircle = min(mincircle,Dist[i][j]+G [j][k]+G [k][i]);
    //通常的 floyd 部分:
    for(int i=1;i<=n; i++)
        for(int j=1;j<=n; j++){
            int temp = Dist[i][k] + Disk[k][j];
            if(temp < Dist[i][j])
                Dist[i][j] = Dist[j][i] = temp;
        }
}

2.记录路径:

#include<algorithm>
using namespace std;
const int MAXN=105;
const int INF=10000000;
int dist[MAXN][MAXN],g[MAXN][MAXN];
int fa[MAXN][MAXN],path[MAXN];
int n,m,num,minc;
void Floyd(){
     int i,j,k,p,tmp;
     minc=INF;
     for(k=1;k<=n;k++){
      for(i=1;i<k;i++)
        for(j=i+1;j<k;j++){
           tmp=dist[i][j]+g[i][k]+g[k][j];
           if(tmp<minc) {//找到更优解
              minc=tmp;
              num=0;
              p=j;
              while(p!=i) {//逆向寻找前驱结点直到找到最前面的i,i->…->j
                path[num++]=p;
                p=fa[i][p];//fa[i][j]保存的不是k,而是fa[k][j].
              }
              path[num++]=i;
              path[num++]=k;
           }
       }
       for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
          tmp=dist[i][k]+dist[k][j];
          if(dist[i][j]>tmp) {
               dist[i][j]=tmp;
               fa[i][j]=fa[k][j];
             }
          }
     }
}

至于这个fa是怎么操作的。。。先背过吧。。。 

 

posted @ 2016-06-23 13:13  FuTaimeng  阅读(770)  评论(1编辑  收藏  举报