前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最短路径之弗洛伊德算法

最短路径之弗洛伊德算法

作者头像
每天学Java
发布2020-06-01 10:44:01
7580
发布2020-06-01 10:44:01
举报
文章被收录于专栏:每天学Java每天学Java

前面Dijkstra算法和Bellman-Ford算法解决了单源最短路径问题,但是如果需要获取图中任意两顶点的最短距离呢?我们可以使用前面两个算法我们可以遍历每个顶点得到每个顶点的单源最短距离,但是最短路径算法中提供了一种更为简单的算法 帮助我们实现任意两顶点最短距离(Floyd)。

弗洛伊德算法

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名

核心思路

使用邻接矩阵G来表示图,初始化G,将不可直达的顶点初始化为无穷大,定义k结点,遍历N个顶点->k,使用k作为任意两顶点i,j之间的中介点, 如果G[i][j]>G[i][k]+G[k][j],则执行松弛操作,这里我们就可以理解为什么叫插点法了,将每一个顶点当作中介点放入任意两顶点之间, 如果可以执行松弛操作,则进行松弛。

推导过程
代码语言:javascript
复制
V0->V1 1
V0->V2 2
V1->V2 -1

初始化图G,执行如下操作

第一轮:

第一步:选取V0作为中介点

第二步:插入任意两顶点之间 首先插入V0->V0之间,G[0][0]>G[0][0]+G[0][0],(0>0不满足)无需松弛, 再插入V0->V1之间,G[0][1]>G[0][0]+G[0][1],(1>0+1不满足)无需松弛, 再插入V0->V2之间,G[0][2]>G[0][0]+G[0][2],(2>0+2不满足)无需松弛。

首先插入V1->V0之间,G[1][0]>G[1][0]+G[0][0],(∞>∞+0不满足)无需松弛, 再插入V1->V1之间,G[1][1]>G[1][0]+G[0][1],(∞>∞+1不满足)无需松弛, 再插入V1->V2之间,G[1][2]>G[1][0]+G[0][2],(∞>∞+2不满足)无需松弛。

......

第二轮在选取V1作为中介点,重复上面操作(这一轮会松弛 G[0][2]>G[0][1]+G[1][2]->2>1+(-1) 满足条件,松弛) 第二轮在选取V2作为中介点,重复上面操作

最终得到最短路径

实现代码(C++)
代码语言:javascript
复制
//
//  main.cpp
//  Floyd
//
//  Created by 陈龙
//  Copyright © 2019 陈龙. All rights reserved.
//

#include <iostream>
using namespace std;

int N,E;


int main(int argc, const char * argv[]) {
    //N个顶点,E条边
    cin>>N>>E;
    int u,v,w;
    int G[N][N];
    //初始化无穷大
    for (int i=0; i<N; i++) {//顶点i
        for (int j=0; j<N; j++) {//目标顶点i
            if(i==j)G[i][j]=0;
            else G[i][j]=INT_MAX;
        }
    }
    //构建有向图
    for(int i=0;i<E;i++){
        cin>>u>>v>>w;
        G[u][v] = w;
    }
    //动态规划找中介
    for (int k=0; k<N; k++) {//中介k
        for (int i=0; i<N; i++) {//顶点i
            for (int j=0; j<N; j++) {//目标顶点i
                if((G[i][k]!=INT_MAX && G[k][j] !=INT_MAX ) && G[i][j]>G[i][k]+G[k][j]){
                    G[i][j]=G[i][k]+G[k][j];
                }
            }
        }
    }
    //最短路径
    cout<<"===";
    for (int i=0; i<N; i++) {//顶点i
        for (int j=0; j<N; j++) {//目标顶点i
            cout<<i<<" "<<j<<" "<<G[i][j]<<endl;
        }
    }
    return 0;
}

/*
     eg:
     3 3
     0 1 1
     0 2 2
     1 2 -1
/*
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 弗洛伊德算法
  • 核心思路
  • 推导过程
  • 实现代码(C++)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档