[Python] 弗洛伊德(Floyd)算法求图的直径并记录路径


相关概念

对于一个图G=(V, E),求图中两点u, v间最短路径长度,称为图的最短路径问题。最短路径中最长的称为图的直径

其中,求图中确定的某两点的最短路径算法,称为单源最短路径算法。求图中任意两点间的最短路径算法,称为多源最短路径算法。

常用的路径算法有:

  • Dijkstra算法
  • SPFA算法\Bellman-Ford算法
  • Floyd算法\Floyd-Warshall算法
  • Johnson算法

其中最经典的是Dijkstra算法和Floyd算法。Floyd算法是多源最短路径算法,可以直接求出图中任意两点间的距离,因此只要取其中最大的就可以得到图的直径。

Floyd算法

算法思想

假设Dis(i,j)为节点u到节点v的最短路径的距离(最短路径长度),对于每一个节点k,检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,说明从i到k再到j的路径比i直接到j的路径短,便记录Dis(i,j) = Dis(i,k) + Dis(k,j)。因此,当遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

算法特点

  • 使用了动态规划思想
  • 可以计算无向图或有向图
  • 核心代码简短(五行)
  • 可以一次性计算出任意两点间的距离
  • 算法复杂度O(n^3),是一个算法

一个关键性问题

在判断Dis(i,k) + Dis(k,j) < Dis(i,j)这个公式时,如果经过k的距离更短就选择k,但是这能否保证此时Dis(i,k)和Dis(k,j)已经取得了最小值呢?

答案是肯定的,可以用数学归纳法证明,参考这篇博客

示例

待求直径的图G

程序输入

2(表示无向图)

8 9 (表示8个顶点,9条边)

1 2 5 (表示顶点1和顶点2之间的距离权重是5)

... ...

程序输出

(邻接矩阵,矩阵元素M[i][j]表示顶点Vi与Vj间的距离)

(各个顶点间的最短路径以及路径长度,对于此例,顶点V4与V6或V8间的距离都是10,是距离最远的两个顶点对)

(此图的直径)

Python源代码

# ----------------------------------------------
# Project: calculate diameter of graph
# Using floyd algorithm
# ----------------------------------------------

# define function: print shortest path
def getPath(i, j):
    if i != j:
        if path[i][j] == -1:
            print(‘-‘, j+1, end=‘‘)
        else:
            getPath(i, path[i][j])
            getPath(path[i][j], j)

def printPath(i, j):
    print(‘ Path:‘, i+1, end=‘‘)
    getPath(i, j)
    print()

print(‘---------------- Program start ----------------‘)
# read data
flag = input(‘please input type of graph(1:directed ‘
             ‘graph; 2:undirected graph): ‘)
vertex, edge = input(‘please input the number of ‘
                     ‘vertex and edge: ‘).strip().split()

# initialized
flag = int(flag)
vertex = int(vertex)
edge = int(edge)
inf = 99999999
dis = []  # matrix of the shortest distance
path = []  # record the shortest path
for i in range(vertex):
    dis += [[]]
    for j in range(vertex):
        if i == j:
            dis[i].append(0)
        else:
            dis[i].append(inf)
for i in range(vertex):
    path += [[]]
    for j in range(vertex):
        path[i].append(-1)

# read weight information
print(‘please input weight info(v1 v2 w[v1,v2]): ‘)
for i in range(edge):
    u, v, w = input().strip().split()
    u, v, w = int(u)-1, int(v)-1, int(w)
    if flag == 1:
        dis[u][v] = w
    elif flag == 2:
        dis[u][v] = w
        dis[v][u] = w
print(‘the weight matrix is:‘)
for i in range(vertex):
    for j in range(vertex):
        if dis[i][j] != inf:
            print(‘%5d‘ % dis[i][j], end=‘‘)
        else:
            print(‘%5s‘ % ‘∞‘, end=‘‘)
    print()

# floyd algorithm
for k in range(vertex):
    for i in range(vertex):
        for j in range(vertex):
            if dis[i][j] > dis[i][k] + dis[k][j]:
                dis[i][j] = dis[i][k] + dis[k][j]
                path[i][j] = k
print(‘===========================================‘)

# output the result
print(‘output the result:‘)
if flag == 1:
    for i in range(vertex):
        for j in range(vertex):
            if (i != j) and (dis[i][j] != inf):
                print(‘v%d ----> v%d  tol_weight:‘
                      ‘%3d‘ % (i+1, j+1, dis[i][j]))
                printPath(i, j)
            if (i != j) and (dis[i][j] == inf):
                print(‘v%d ----> v%d  tol_weight:‘
                      ‘  ∞‘ % (i+1, j+1))
                printPath(i, j)

if flag == 2:
    for i in range(vertex):
        for j in range(i+1, vertex):
            print(‘v%d <----> v%d  tol_weight:‘
                  ‘%3d‘ % (i+1, j+1, dis[i][j]), ‘‘, end=‘‘)
            printPath(i, j)
print()
for i in range(vertex):
    for j in range(vertex):
        if dis[i][j] == inf:
            dis[i][j] = 0
# max(max(dis)): the max item of two dimension matrix
print(‘>> the diameter of graph: %d <<‘ % max(max(dis)))
print(‘-------------- Program end ----------------‘)

Reference

最短路径_百度百科

最短路径—Dijkstra算法和Floyd算法

最短路径问题---Floyd算法详解 - CSDN博客

Floyd算法(记录路径) - CSDN博客

原文地址:https://www.cnblogs.com/Ran-Chen/p/9219716.html

时间: 2024-10-10 23:20:03

[Python] 弗洛伊德(Floyd)算法求图的直径并记录路径的相关文章

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

_DataStructure_C_Impl:Floyd算法求有向网N的各顶点v和w之间的最短路径

#include<stdio.h> #include<stdlib.h> #include<string.h> typedef char VertexType[4]; typedef char InfoPtr; typedef int VRType; #define INFINITY 100000 //定义一个无限大的值 #define MaxSize 50 //最大顶点个数 typedef int PathMatrix[MaxSize][MaxSize][MaxSiz

C# 弗洛伊德(Floyd)算法

弗洛伊德(Floyd)算法 主要是用于计算图中所有顶点对之间的最短距离长度的算法,如果是要求某一个特定点到图中所有顶点之间的最短距离可以用Dijkstra(迪杰斯特拉)算法来求. 弗洛伊德(Floyd)算法的算法过程是: 1.从任意一条单边路径开始.所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大. 2.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短.如果是更新它. 把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i

用python实现欧几里德算法求最大公约数

方法1: def gcd(x, y):   while n:       x, y = y, x % y   return x 方法2: def yue(x,y):      if y:              return gcd(y,x%y)      else:            return x 用python实现欧几里德算法求最大公约数,布布扣,bubuko.com

Floyd 算法求多源最短路径

Floyd算法: Floyd算法用来找出每对顶点之间的最短距离,它对图的要求是,既可以是无向图也可以是有向图,边权可以为负,但是不能存在负环. 基本算法: Floyd算法基于动态规划的思想,以 u 到 v 的最短路径至少经过前 k 个点为转移状态进行计算,通过 k 的增加达到寻找最短路径的目的.当 k 增加 1 时,最短路径要么不边,如果改变,必经过第 k 各点,也就是说当起点 u 到第 k 个点的最短距离加上第 k 个点到终点 v 的最短路径小于不经过第 k 个节点的最优最短路经长度的时候更新

poj 3895 Cycles of Lanes 修改tarjan算法求图中最大环

题意: 给一个边权均为1的无向图,求图中的最大环. 分析: tarjan算法一般用来强连通分量,它依次访问图中的各个强连通分量,这题要求最大环,而环也是强连通分量的一部分,所以可以在每个点访问其他点时修改时间戳,达到每个环上时间戳连续的目的,这样当访问到一个栈中节点时就能直接更新最大环了.根据同样的思路,即使边权任意,也可求最大环或最小环. 代码: //poj 3895 //sep9 #include <iostream> #include <vector> #include &l

FLOyd算法 求任意最短路

此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM"上.同年Stephen Warshall(史蒂芬·沃舍尔)也独立发表了这个算法.Robert W.Floyd这个牛人是朵奇葩,他原本在芝加哥大学读的文学,但是因为当时美国经济不太景气,找工作比较困难,无奈之下到西屋电气公司当了一名计算机操作员,在IBM650机房值夜班,并由此开始了他的计算机生涯. 作者:ahalei来源:51CTO博客|2014-03-26

JS实现最短路径之弗洛伊德(Floyd)算法

弗洛伊德算法是实现最小生成树的一个很精妙的算法,也是求所有顶点至所有顶点的最短路径问题的不二之选.时间复杂度为O(n3),n为顶点数. 精妙之处在于:一个二重初始化,加一个三重循环权值修正,完成了所有顶点至所有顶点的的最短路径计算,代码及其简洁 JS实现: //定义邻接矩阵 let Arr2 = [ [0, 1, 5, 65535, 65535, 65535, 65535, 65535, 65535], [1, 0, 3, 7, 5, 65535, 65535, 65535, 65535], [

弗洛伊德(Floyd)算法

1 #include <stdio.h> 2 3 #define MAXVEX 20 //最大顶点数 4 #define INFINITY 65535 //∞ 5 6 7 typedef struct 8 {/* 图结构 */ 9 int vexs[MAXVEX];//顶点下标 10 int arc[MAXVEX][MAXVEX];//矩阵 11 int numVertexes, numEdges;//顶点数和边数 12 }MGraph; 13 14 //用户定义类型 15 typedef i