zoukankan      html  css  js  c++  java
  • 图的最短路径问题

    今天一定要把图的最短路径给解决了。

    (1)Floyd算法。O(n^3)。但是代码极其简介。

    试用范围:求任意两点之间的最短路径。(Dijkstra。迪克斯特拉是求某个顶点到其他任何顶点的。对他的n个顶点都来一次Dijkstra等价于Floyd。复杂度是他的O(n^2)*n == O(n^3))。

    思路和代码:其实就是说i直接到j的距离如果比i到了k,k再到j之和大,那么久更替。k可以取所有顶点。

    import java.util.Arrays;
    
    public class Main {
        public final static int INFINITY = Integer.MAX_VALUE;
        public static void main(String[] args) {
            int[][] graph = { { 0, 2, 6, 4}, { INFINITY, 0, 3, INFINITY}, { 7, INFINITY, 0, 1}, { 5, INFINITY, 12, 0}};
            floyd(graph);
            for (int i = 0; i < 4; i++) {
                System.out.println(Arrays.toString(graph[i]));
            }
        }
        
        public static void floyd(int[][] graph) {
            for (int k = 0; k < graph.length; k++) {
                for (int i = 0; i < graph.length; i++) {
                    for (int j = 0; j < graph.length; j++) {
                        if (graph[i][k] < INFINITY && graph[k][j] < INFINITY && graph[i][j] > graph[i][k] + graph[k][j]) {
                            graph[i][j] = graph[i][k] + graph[k][j];
                        }
                    }
                }
            }
        }
    }
    View Code

     

    (2)Dijkstra算法。O(n^2)。

    试用范围:求指定的一个点v0到其余各个顶点的最短路径。专业术语:单源最短路径。在函数上可以随意指定要求哪个点到哪个点

    思路:建立一个distance[n]来表示到所有点的距离。首先,把第一行拷贝了。哪个点是源点,那么distance[v0] == 0;

    代码:

    import java.util.Arrays;
    
    public class Main {
        public final static int INFINITY = Integer.MAX_VALUE;
        public static void main(String[] args) {
            int[][] graph = { { 0, 2, 6, 4}, { INFINITY, 0, 3, INFINITY}, { 7, INFINITY, 0, 1}, { 5, INFINITY, 12, 0}};
    //        floyd(graph);
    //        for (int i = 0; i < 4; i++) {
    //            System.out.println(Arrays.toString(graph[i]));
    //        }
            int[] distance = new int[graph.length];
            dijsktra(graph, distance, 1);
            System.out.println(Arrays.toString(distance));
            
        }
        public static void dijsktra(int[][] graph, int[] distance, int v0) { // 从v0到其他顶点的路径
            boolean[] finish = new boolean[graph.length];
            for (int i = 0; i < graph.length; i++) {
                distance[i] = graph[v0][i];
            }
            finish[v0] = true;
            distance[v0] = 0;
            int minIndex = -1;
            for (int n = 1; n < graph.length; n++) { // n次
                int min = Integer.MAX_VALUE;
                for (int i = 0; i < graph.length; i++) {
                    if (!finish[i]) {
                        if (distance[i] < min) {
                            min = distance[i];
                            minIndex = i;
                        }
                    }
                }
                finish[minIndex] = true;
                for (int i = 0; i < graph.length; i++) {
                    if (!finish[i]) {
                        if (graph[minIndex][i] < INFINITY && graph[minIndex][i] + min < distance[i]) {
                            distance[i] = min + graph[minIndex][i];
                        }
                    }
                }
            }
        }
    }
    View Code

    如果是求第一个到最后一个,可以优化为:

    public static int dijsktraLast(int[][] graph, int[] distance, int v0) { // 从v0到其他顶点的路径
            boolean[] finish = new boolean[graph.length];
            for (int i = 0; i < graph.length; i++) {
                distance[i] = graph[v0][i];
            }
            finish[v0] = true;
            
    //        distance[v0] = 0;
            int minIndex = -1;
            for (int n = 1; n < graph.length; n++) { // n次
                int min = Integer.MAX_VALUE;
                for (int i = 0; i < graph.length; i++) {
                    if (!finish[i]) {
                        if (distance[i] < min) {
                            min = distance[i];
                            minIndex = i;
                        }
                    }
                }
                if (minIndex == graph.length - 1) {
                    return min;
                }
                finish[minIndex] = true;
                
                for (int i = 0; i < graph.length; i++) {
                    if (!finish[i]) {
                        if (graph[minIndex][i] < INFINITY && graph[minIndex][i] + min < distance[i]) {
                            distance[i] = min + graph[minIndex][i];
                        }
                    }
                }
            }
            return distance[graph.length - 1];
        }
    View Code

     

    (3)Bellman-ford算法。O(NM)

    试用范围:稀疏图。可以解决负权

    思路和代码:其实就是建立一个u[i]顶点到v[i]顶点的权值为w[i]。

     代码:

    import java.util.Arrays;
    
    public class Main {
    
        public static int INFINITY = Integer.MAX_VALUE;
        public static void main(String[] args) {
            int[] u = {0, 0, 0, 1, 2, 2, 3, 3};
            int[] v = {3, 2, 1, 2, 0, 3, 2, 0}; 
            int[] w = {4, 6, 2, 3, 7, 1, 12, 5 };
            int n = 4;
            int m = 8;
            int[] distance = new int[n];
            bellmanFord(distance, u, v, w, n, m, 3);
            System.out.println(Arrays.toString(distance));
        }
        public static void bellmanFord(int[] distance, int[] u, int[] v, int[] w, int n, int m, int start) { // start 表示第几个顶点到其他的
            for (int i = 0; i < n; i++) {
                distance[i] = INFINITY;
            }
            distance[start] = 0;
            for (int k = 0; k <= n - 1; k++) { //需要来进行n-1轮
                int check = 0;
                for (int i = 0; i < m; i++) {
                    if (distance[u[i]] != INFINITY && distance[v[i]] > distance[u[i]] + w[i]) {
                        distance[v[i]] = distance[u[i]] + w[i];
                        check = 1;
                    }
                }
                if (check == 0) {
                    break;
                }
            }
        }
    }
    View Code

     

  • 相关阅读:
    java web 学习 --第七天(Java三级考试)
    java web 学习 --第六天(Java三级考试)
    java web 学习 --第五天(Java三级考试)
    java web 学习 --第四天(Java三级考试)
    java web 学习 --第三天(Java三级考试)
    java web 学习 --第二天(Java三级考试)
    java web 学习 --第一天(Java三级考试)
    shell 监控局域网的主机是否up
    How to call getClass() from a static method in Java?
    不知道数据库中表的列类型的前提下,使用JDBC正确的取出数据
  • 原文地址:https://www.cnblogs.com/yueyebigdata/p/5354024.html
Copyright © 2011-2022 走看看