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是怎么操作的。。。先背过吧。。。