10/21/2018 Bellman-Ford 算法

Background:

当负权存在时,最短路不一定存在。如果最短路存在,一定存在一个不含环的最短路。

理由如下:在边权可正可负的图中,环有零环、正环和负环三种。如果包含零环或正环,去掉以后路径不会变长;如果包含负环,则意味着最短路不存在。(路径可以一直在负环中循环,则权值会无限小)

既然不含环,则最短路最多只经过(不算起点)《10/21/2018 Bellman-Ford 算法》个结点,可以通过《10/21/2018 Bellman-Ford 算法》 轮松弛操作得到。代码如下(起点为0):

for (int i = 0; i < n; i++) d[i] = INF;
d[0] = 0;
for (int k = 0; k < n - 1; k++) {
	int x = u[i], y = v[i];
	if (d[x] < INF) d[y] = min(din[y], d[x] + w[i]);
}

Algorithm Details: 

Input: Graph and a source vertex src

Output: Shortest distance to all vertices from src. If there is a negative weight cycle, then the shortest distances are not calculated, the negative weight cycle is reported. 

1) This step initializes distances from source to all vertices as infinite and distance to the source itself is 0. Create an array dist[] of size |V| with all values as infinite except dist[src] where src is the source vertex

2) This step calculates the shortest distance Do following |V| – 1 times where |V| is the number of vertices in the given graph.

    a) Do following for each edge u-v

      if dist[v] > dist[u] + weight of edge uv, then update dist[v]

        dist[v] = dist[u] + weight of edge u

3) This step reports if there is a negative weight cycle in the graph. Do following for each u-v

    if dist[v] > dist[u] + weight of edge uv, then “Graph contains negative cycle”

    The idea of step 3 is, step 2 guarantees the shortest distances if the graph doesn’t contain negative weight cycle. If we iterate through all edges one more time and get a shorter path for any vertex, then there is a negative weight cycle.

 

Idea: Like other Dynamic Programming Problems, the algorithm calculates shortest paths in bottom-up manner. It first calculates the shortest distances which have at most one edge in the path. Then, it calculates shortest paths with at most 2 edges, and so on. After the ith iteration of the outer loop, the shortest paths with at most i edges  are calculated. There can be maximum |V| – 1 edges in any simple path, that is why the outer loop runs |V| – 1 times. The idea is, assuming that there is no negative weight cycle, if have calculated shortest paths with at most i edges, then an iteration over all edges guarantees to give the shortest path with at-most (i + 1) edges. 

class Graph3 {
    class Edge {
        int src, dest, weight;
        Edge() {
            src = dest = weight = 0;
        }
    };
    
    int V, E;
    Edge edge[];
     Graph3(int v, int e) {
        V = v;
        E = e;
        edge = new Edge[e];
        for (int i = 0; i < e; i++) {
            edge[i] = new Edge();
        }
    }
    void BellmanFord(Graph3 graph, int src) {
         int V = graph.V, E = graph.E;
         int dist[] = new int[V];
         //Step1: 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;
         
         //Step2: Relax all edges |V| - 1 time. 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;
            }
        }
        //Step3: check for negative-weight cycles. The above steps 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");
        }
    }
}

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/DreamyHacker/article/details/83247120
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞