zoukankan      html  css  js  c++  java
  • Bellman–Ford and SPFA Algorithm

    Bellman–Ford Algorithm 是由 Richard Bellman(DP创始人) 和 Ford 共同创立的,求解单源最短路径问题的一种算法。它的原理是对图进行顶点个数减一次的松弛操作(逐渐逼近最终解的过程),得到所有顶点到源点的最短路径。该算法优于dijkstra的方面在于其边的权值可以是负数(负权环可以无限降低cost)、实现简单,缺点是时间复杂度过高,为O(V*E)。

    package datastructure.graph;
    
    // A Java program for Bellman-Ford's single source shortest path
    // algorithm.
    
    // A class to represent a connected, directed and weighted graph
    class BF {
        // A class to represent a weighted edge in graph
        class Edge {
            int src, dest, weight;
            Edge()
            {
                src = dest = weight = 0;
            }
        };
    
        int V, E;
        Edge edge[];
    
        // Creates a graph with V vertices and E edges
        BF(int v, int e)
        {
            V = v;
            E = e;
            edge = new Edge[e];
            for (int i = 0; i < e; ++i)
                edge[i] = new Edge();
        }
    
        // The main function that finds shortest distances from src
        // to all other vertices using Bellman-Ford algorithm. The
        // function also detects negative weight cycle
        void BellmanFord(BF graph, int src)
        {
            int V = graph.V, E = graph.E;
            int dist[] = new int[V];
    
            // Step 1: Initialize distances from src to all other
            // vertices as INFINITE
            for (int i = 0; i < V; ++i)
                dist[i] = Integer.MAX_VALUE;
            dist[src] = 0;
    
            // Step 2: Relax all edges |V| - 1 times. A simple
            // shortest path from src to any other vertex can
            // have at-most |V| - 1 edges
            for (int i = 1; i < V; ++i) {
                for (int j = 0; j < E; ++j) {
                    int u = graph.edge[j].src;
                    int v = graph.edge[j].dest;
                    int weight = graph.edge[j].weight;
                    if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v])
                        dist[v] = dist[u] + weight;
                }
            }
    
            // Step 3: check for negative-weight cycles. The above
            // step guarantees shortest distances if graph doesn't
            // contain negative weight cycle. If we get a shorter
            // path, then there is a cycle.
            for (int j = 0; j < E; ++j) {
                int u = graph.edge[j].src;
                int v = graph.edge[j].dest;
                int weight = graph.edge[j].weight;
                if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) {
                    System.out.println("Graph contains negative weight cycle");
                    return;
                }
            }
            printArr(dist, V);
        }
    
        // A utility function used to print the solution
        void printArr(int dist[], int V)
        {
            System.out.println("Vertex Distance from Source");
            for (int i = 0; i < V; ++i)
                System.out.println(i + "		" + dist[i]);
        }
    
        // Driver method to test above function
        public static void main(String[] args)
        {
            int V = 5; // Number of vertices in graph
            int E = 8; // Number of edges in graph
    
            BF graph = new BF(V, E);
    
            // add edge 0-1 (or A-B in above figure)
            graph.edge[0].src = 0;
            graph.edge[0].dest = 1;
            graph.edge[0].weight = -1;
    
            // add edge 0-2 (or A-C in above figure)
            graph.edge[1].src = 0;
            graph.edge[1].dest = 2;
            graph.edge[1].weight = 4;
    
            // add edge 1-2 (or B-C in above figure)
            graph.edge[2].src = 1;
            graph.edge[2].dest = 2;
            graph.edge[2].weight = 3;
    
            // add edge 1-3 (or B-D in above figure)
            graph.edge[3].src = 1;
            graph.edge[3].dest = 3;
            graph.edge[3].weight = 2;
    
            // add edge 1-4 (or A-E in above figure)
            graph.edge[4].src = 1;
            graph.edge[4].dest = 4;
            graph.edge[4].weight = 2;
    
            // add edge 3-2 (or D-C in above figure)
            graph.edge[5].src = 3;
            graph.edge[5].dest = 2;
            graph.edge[5].weight = 5;
    
            // add edge 3-1 (or D-B in above figure)
            graph.edge[6].src = 3;
            graph.edge[6].dest = 1;
            graph.edge[6].weight = 1;
    
            // add edge 4-3 (or E-D in above figure)
            graph.edge[7].src = 4;
            graph.edge[7].dest = 3;
            graph.edge[7].weight = -3;
    
            graph.BellmanFord(graph, 0);
        }
    }
    // Contributed by Aakash Hasija

    Shortest Path Faster Algorithm (SPFA)  - Bellman–Ford的队列改进算法

    The Shortest Path Faster Algorithm (SPFA) is an improvement of the Bellman–Ford algorithm which computes single-source shortest paths in a weighted directed graph. The algorithm is believed to work well on random sparse graphs(稀疏图) and is particularly suitable for graphs that contain negative-weight edges.

    • Worst case time complexity: Θ(VE)
    SPFA(v):
        d[i] = infinity for each vertex i
        d[v] = 0
        queue q
        q.push(v)
        while q is not empty
            u = q.front()
            q.pop()
            for each i in adj[u]
                if d[i] > d[u] + w(u,i)
                    then d[i] = d[u] + w(u,i)
                    if i is not in q
                        then q.push(i)

    https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/

    https://iq.opengenus.org/shortest-path-faster-algorithm/

  • 相关阅读:
    android WebView总结
    Java抓取网页数据(原网页+Javascript返回数据)
    Linux之旅(1): diff, patch和quilt (下)
    浅谈UML的概念和模型之UML九种图
    基于注解的Spring MVC
    Hibernate自增列保存失败的问题
    京东,你玩我?
    MySQL 通配符学习小结
    Java中怎样由枚举常量的ordinal值获得枚举常量对象
    HDU 4588 Count The Carries 计算二进制进位总数
  • 原文地址:https://www.cnblogs.com/lnas01/p/12465404.html
Copyright © 2011-2022 走看看