Floyd-Warshall求图中任意两点的最短路径

原创



  除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径。

  从图中任取两点A、B,A到B的最短路径无非只有两种情况:

  1:A直接到B这条路径即是最短路径(前提是存在此路径);

  2:A先通过其他点,再由其他点到B。

  我们并不知道A是否需要通过其他点间接到达B,所以只能比较,用A到B的直接路径和A先通过其他点

再间接到达B的路径长度进行比较,然后更新为较小值。

  上图中若要求顶点4到顶点3的最短路径,可以比较顶点4直接到3的路径和顶点4先到1,再到3的路径。

更新为最小值,此时邻接矩阵matrix[4][3]存储的即为借用了顶点1后4到3的最短路径;然后再借用了1的

基础上再借用顶点2,此时再次比较matrix[4][3]和matrix[4][2]+matrix[2][3],更新为最小值;比较完

毕后matrix[4][3]乃存储了最短路径,求其他任意两点也是如此。

  总结一下,求图中任意两点的最短路径,通过比较一次取一个其他顶点间接到达的最短路径和直接路径

进行比较,更新为最小值即可。

import java.util.*;

public class Floyd_Warshall {

    static int v;    //顶点
    static int e;    //边
    static int matrix[][];

    public static void main(String args[]) {
        Scanner reader=new Scanner(System.in);
        v=reader.nextInt();
        e=reader.nextInt();
        matrix=new int[v+1][v+1];    //编号从1开始
        //矩阵初始化
        for(int i=1;i<=v;i++) {
            for(int j=1;j<=v;j++) {
                if(i==j) {    //顶点本身
                    matrix[i][j]=0;
                }
                else {    //无穷
                    matrix[i][j]=99999;
                }
            }
        }
        //读入边
        for(int i=1;i<=e;i++) {
            int first_City=reader.nextInt();
            int second_City=reader.nextInt();
            int value=reader.nextInt();
            matrix[first_City][second_City]=value;    //有向图
        }
        for(int k=1;k<=v;k++) {    //只允许经过顶点k
            for(int i=1;i<=v;i++) {
                for(int j=1;j<=v;j++) {
                    if(matrix[i][k]+matrix[k][j]<matrix[i][j]) {
                        matrix[i][j]=matrix[i][k]+matrix[k][j];
                    }
                }
            }
        }
        for(int i=1;i<=v;i++) {
            for(int j=1;j<=v;j++) {
                System.out.print(matrix[i][j]+" ");
            }
            System.out.println();
        }
    }
}

测试用例:

输入:

4 8

1 2 2

2 3 3

3 4 1

4 3 12

1 3 6

3 1 7

1 4 4

4 1 5

输出:

0 2 5 4 

9 0 3 4 

6 8 0 1 

5 7 10 0 

12:30:24

2018-07-28

原文地址:https://www.cnblogs.com/chiweiming/p/9381652.html

时间: 2024-11-05 18:46:03

Floyd-Warshall求图中任意两点的最短路径的相关文章

javascript实现有向无环图中任意两点最短路径的dijistra算法

有向无环图 一个无环的有向图称做有向无环图(directed acycline praph).简称DAG 图.DAG 图是一类较有向树更一般的特殊有向图, dijistra算法 摘自 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijk

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

相关概念 对于一个图G=(V, E),求图中两点u, v间最短路径长度,称为图的最短路径问题.最短路径中最长的称为图的直径. 其中,求图中确定的某两点的最短路径算法,称为单源最短路径算法.求图中任意两点间的最短路径算法,称为多源最短路径算法. 常用的路径算法有: Dijkstra算法 SPFA算法\Bellman-Ford算法 Floyd算法\Floyd-Warshall算法 Johnson算法 其中最经典的是Dijkstra算法和Floyd算法.Floyd算法是多源最短路径算法,可以直接求出图

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

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

求二叉树中任意两个结点的距离

求二叉树中任意两个结点的距离 实现步骤: 计算跟到第一个结点的距离: 计算跟到第二个结点的距离: 计算lca: 计算跟到lca结点的距离: 结果为(1) + (2) - 2 * (4),因为重复计算了两次的从跟到lca结点的距离: 1 class Node(object): def __init__(self, value=0): self.value = value self.left = self.right = None def get_path_length(root, n, path)

求数组中任意两个数之间所有数字的和

303. Range Sum Query - Immutable   求数组中任意两个数之间所有数字的和 QuestionEditorial Solution My Submissions Total Accepted: 37248 Total Submissions: 146945 Difficulty: Easy Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j),

求图中某点到另一点的通路

图的搜索方法有DFS和BFS,但是这两个算法不能直接得到(其实是我不会)图中任意一点到另外一点的通路路径,以图中某个点作为起点,另外一点作为终点,从终点开始,利用邻接表,从后向前查找,首先查找可以直接到终点的节点,放入集合S1中,然后再查找可以直接到S1的节点,存入集合S2,只到找到起点为止.代码如下: 1 public static void getReachableNodeCollection(){ 2 ArrayList<ArrayList<Integer>> reachab

求图中欧拉回路数量

问题描述:输入点数n.边数m.每条边连接的两个点a,b,求此无向图中不包括一个点本身的欧拉回路数量,重复不计: 解决此问题,则需要在深搜的基础上判断新搜出的欧拉回路是否已经被走过,可以利用搜索时所打的标记来判断: 使用邻接表,需要注意在无向图中连接两点有两条边,要同时考虑: 以下为代码: #include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,m,cnt[105],ct,q

求水洼的问题(或者是说求图中连通子图的个数)----深度优先算法

遇到这个题的时候,不太容易快速的想到思路:可能会比较容易想到使用递归的思想:但是具体怎么写呢?其实这个题就相当于是图论中的求连通图,很容易应该想到的是深度优先搜索或者是广度优先搜索:我们就用深度优先算法来求这个题目:直接求有几个区域不好求,那么我们换个思路来求,这种题就是这样,直接求不好求,但是当我们转换一下思路之后就豁然开朗: 我们遍历所有的点,当遇到有水的点时,就将它周围的(八个方向)所有的水点都消除:所以在主遍历for循环中遇到几个水点就是有几个水洼: /*****************

[BC]求数组中任意两个数的公约数,,多种情况取最大值

#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> using namespace std; int main() { int t,i,c,j,n,x,max,k; int a[100005]; scanf("%d",&t); for(j=1;j<=t;j++) {