算法基础 - 多源点最短路径(Floyd算法)

Floyd算法

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

思路

路径矩阵

通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

引用自:百度百科

采用松弛技术(松弛操作),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);

状态转移方程

其状态转移方程如下:

map[i,j]:=min{map[i,k]+map[k,j],map[i,j]};

map[i,j]表示i到j的最短距离,K是穷举i,j的断点,map[n,n]初值应该为0,或者按照题目意思来做。

当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路。

其实就是枚举第三个点,看是否能出现 1->3->2的距离比1->2的短

复杂度

时间复杂度: O(N^3);

空间复杂度:O(N^2);

伪代码

For k:=1 to n
For i:=1 to n
For j:=1 to n
    If D[i,j]>D[i,k]+D[k,j] Then
        D[i,j]:=D[i,k]+D[k,j];

代码实现

//
//  main.cpp
//  HiHocoder
//
//  Created by Alps on 16/5/9.
//  Copyright ? 2016年 chen. All rights reserved.
//
#include <iostream>
#include <cstring>
#include <string>

using namespace std;

long long dist[102][102]; //表示最大节点数是101个

long long minNum(long long a, long long b){
    if(a == -1) return b;
    return a < b ? a : b;
}

void floyd(long long dist[][102], int N){
    for(int i = 1; i <= N; i++){
        for(int j = 1; j <= N; j++){
            for(int k = 1; k <= N; k++){
                if(dist[j][i] == -1 || dist[i][k] == -1){
                    continue;//如果没路径别走
                }
                dist[j][k] = minNum(dist[j][k], dist[j][i]+dist[i][k]);
            }
        }
    }
}

int main(){
    int N,M;

    while(cin>>N>>M){
        for(int i = 0; i <= N; i++){
            for(int j = 0; j <= N; j++){
                dist[i][j] = -1; //初始化为-1 表示无穷远
                if(i == j){
                    dist[i][j] = 0;
                }
            }
        }
        int x, y, d;
        for(int i = 0; i < M; i++){
            cin>>x>>y>>d;
            dist[x][y] = minNum(dist[x][y], d);
            dist[y][x] = dist[x][y];//无向图,如果是有向图去掉这个路径
        }
        floyd(dist, N);
        for(int i = 1; i <= N; i++){ //输出整个矩阵
            for(int j = 1; j<= N; j++){
                cout<<dist[i][j]<<" ";
            }
            cout<<endl;
        }
    }

    return 0;
}
时间: 2024-12-12 12:23:56

算法基础 - 多源点最短路径(Floyd算法)的相关文章

算法基础 - 单源点最短路径SPFA

SPFA是非常简单的最短路径算法,思想就是从起点开始,进行宽度优先搜索,不断松弛S点到其他相邻点的距离.如果松弛了点B,则把点B放到队列里.假如点B已经在队列里了,就不要放了,判断在不在队列可以用个数组来表示. 引用一段hihocoder上的解释: 构造一个队列,最开始队列里只有(S, 0)--表示当前处于点S,从点S到达该点的距离为0,然后每次从队首取出一个节点(i, L)--表示当前处于点i,从点S到达该点的距离为L,接下来遍历所有从这个节点出发的边(i, j, l)--表示i和j之间有一条

最短路径—Floyd算法

Floyd算法 所有顶点对之间的最短路径问题是:对于给定的有向网络G=(V,E),要对G中任意两个顶点v,w(v不等于w),找出v到w的最短路径.当然我们可以n次执行DIJKSTRA算法,用FLOYD则更为直接,两种方法的时间复杂度都是一样的. 1.定义概览 Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包.Floyd-Warshall算法的时间复杂度

(转)最短路径Floyd算法

本文转自:https://blog.csdn.net/jack_20/article/details/78031310 Floyd算法求所有顶点到所有顶点的最短路径,时间复杂度也为O(n^3),但其算法非常简洁优雅.为了能讲明白该算法的精妙所在,先来看最简单的案例. 下图左部分是一个最简单的3个顶点连通网图. 先定义两个数组D[3][3]和P[3][3],D代表顶点到顶点的最短路径权值和的矩阵,P代表对应顶点的最小路径的前驱矩阵.在未分析任何顶点之前,我们将D命 名为D-1 ,其实它就是初始的图

多源最短路径Floyd算法

多源最短路径是求图中任意两点间的最短路,采用动态规划算法,也称为Floyd算法.将顶点编号为0,1,2...n-1首先定义dis[i][j][k]为顶点 i 到 j 的最短路径,且这条路径只经过最大编号不超过k的顶点.于是我们最终要求的是dis[i][j][n-1].状态转移方程如下: dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]}; 状态转移方程的解释:在计算dis[i][j][k]的时候,我们考虑 i 到 j 是否

最短路径(Floyd)算法

#include <stdio.h>#include <stdlib.h> /* Floyd算法 */ #define VNUM 5#define MV 65536 int P[VNUM][VNUM];int A[VNUM][VNUM];int Matrix[VNUM][VNUM] ={    {0, 10, MV, 30, 100},    {MV, 0, 50, MV, MV},    {MV, MV, 0, MV, 10},    {MV, MV, 20, 0, 60},  

单源最短路径——Floyd算法

正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3). Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B.所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,

Bellman-Ford算法——求解单源点最短路径问题

Bellman-Ford算法与另一个非常著名的Dijkstra算法一样,用于求解单源点最短路径问题.Bellman-ford算法除了可求解边权均非负的问题外,还可以解决存在负权边的问题(意义是什么,好好思考),而Dijkstra算法只能处理边权非负的问题,因此 Bellman-Ford算法的适用面要广泛一些.但是,原始的Bellman-Ford算法时间复杂度为O(VE),比Dijkstra算法的时间复杂度高,所以常常被众多的大学算法教科书所忽略,就连经典的<算法导论>也只介绍了基本的Bellm

图论之最短路径floyd算法

Floyd算法是图论中经典的多源最短路径算法,即求任意两点之间的最短路径. 它可采用动态规划思想,因为它满足最优子结构性质,即最短路径序列的子序列也是最短路径. 举例说明最优子结构性质,上图中1号到5号的最短路径序列<1,2,4,5>,其子序列<1,2,4>也是最短路径. 在动态规划算法中,处于首要位置.且也是核心理念之一的就是状态的定义. 动态转移的基本思想可以认为是建立起某一状态和之前状态的一种转移表示. d[k][i][j]定义为"只能使用第1号到第k号点作为中间媒

最短路径——Floyd算法

如何求一张图中任意两顶点之间的最短路径长度,这里写一种最简单的算法——Floyd算法: 1 #include<stdio.h> 2 3 #define inf 9999 4 5 int main() 6 { 7 int e[10][10]; //用邻接矩阵表示图 8 printf("请输入顶点和边的数目:"); 9 int n,m; 10 scanf("%d%d",&n,&m); 11 for(int i=0;i<n;i++) 12