zoukankan      html  css  js  c++  java
  • SPFA

    一、解决问题

    从图中的某个顶点出发到达另一个顶点的最短路径。

    二、算法思路

    Shortest Path Faster Algorithm (SPFA)。一般认为是队列优化的贝尔曼-福特算法。是一个用于求有向带权图单源最短路径的算法,并且适用于有负权重的图。如果一个顶点被加入了超过顶点的个数,则这个图就有负环

    基本思路

    • 每个节点都用于松弛其相邻节点的备选节点。
    • 维护一个备选节点队列
    • 仅有节点被松弛后才会放入队列
    • 上述流程不断重复直到队列没有节点

    伪代码:

     1 function spfa(G, s):
     2     //初始化所有节点都是最大距离
     3     for each vertex != s in G:
     4         d[vertex] = inf
     5     d[s] = 0
     6     offer s into queue
     7     while(queue is not empty):
     8         u = poll queue
     9         for each v in edge(u):
    10             if d[u] + w[u, v] < d[v]:
    11                 d[v] = d[u] + w[u,v]
    12                 if v not in queue:
    13                     offer v into queue

    三、图例

    首先算一下最短路径为了用来验证

    distance(1,5) = 8
    distance(1,4) = 3
    distance(1,2) = 9
    distance(1,3) = 11
    distance(1,6) = 12

    过程

    • d[a] 为源点到a的距离
    • poll为从队列取出点
    • offer为每次放入队列的点
    • q为队列
    • 红色的为最后的结果

    四、 Code (这里面的图表示形式用链式前向星更简洁一些)

     1 package algorithm;
     2 
     3 
     4 import java.util.*;
     5 
     6 public class SPFATest {
     7     private static final int INF = 0x7fffffff;
     8     private static class Edge {
     9         int source;
    10         int target;
    11         int weight;
    12 
    13         private Edge(int source, int target, int weight){
    14             this.source = source;
    15             this.target = target;
    16             this.weight = weight;
    17         }
    18     }
    19     public static class Graph {
    20         
    21 
    22         int[] nodes;
    23         HashMap<Integer, List<Edge>> nodeWithEdges;
    24 
    25         private Graph init(int[] nodes, List<Edge> edges) {
    26             this.nodes = nodes;
    27             nodeWithEdges = new HashMap<>();
    28             for (Edge edge : edges) {
    29                 List<Edge> edgeTemp = nodeWithEdges.getOrDefault(edge.source, new ArrayList<>());
    30                 edgeTemp.add(edge);
    31                 nodeWithEdges.put(edge.source, edgeTemp);
    32             }
    33             return this;
    34         }
    35 
    36         public int[] getAllNodes() {
    37             return this.nodes;
    38         }
    39 
    40         private List<Edge> getEdgesOfNode(int node) {
    41             return nodeWithEdges.get(node);
    42         }
    43     }
    44 
    45     public static int[] SPFA(int source, Graph graph) {
    46         int n = graph.nodes.length;
    47         int[] d = new int[n+1];
    48         for (int i = 0; i <= n; i++) {
    49             d[i] = INF;
    50         }
    51         d[source] = 0;
    52         boolean[] nodeExistsInQ = new boolean[n+1];
    53         Deque<Integer> deque = new ArrayDeque<>();
    54         deque.offer(source);
    55         nodeExistsInQ[source] = true;
    56 
    57         while (!deque.isEmpty()) {
    58             int u = deque.poll();
    59             nodeExistsInQ[u] = false;
    60             if(graph.getEdgesOfNode(u) == null) continue;
    61 
    62             for (Edge edge : graph.getEdgesOfNode(u)) {
    63                 int v = edge.target;
    64                 if (d[u] + edge.weight < d[v]) {
    65                     d[v] = edge.weight + d[u];
    66 
    67                     if(!nodeExistsInQ[v]){
    68                         deque.offer(v);
    69                         nodeExistsInQ[u] = true;
    70                     }
    71                 }
    72             }
    73         }
    74         return d;
    75     }
    76 
    77     public static void main(String [] args){
    78         int []nodes = new int[]{1,2,3,4,5,6};
    79         List<Edge> edges = new ArrayList<>();
    80         edges.add(new Edge(1,2,9));
    81         edges.add(new Edge(1,4,3));
    82         edges.add(new Edge(1,5,13));
    83         edges.add(new Edge(2,4,7));
    84         edges.add(new Edge(2,3,2));
    85         edges.add(new Edge(3,4,20));
    86         edges.add(new Edge(3,6,1));
    87         edges.add(new Edge(4,5,5));
    88         edges.add(new Edge(4,6,19));
    89 
    90         Graph graph = new Graph().init(nodes, edges);
    91 
    92         int []d = SPFA(1, graph);
    93         for(int i = 1; i <= nodes.length; i++){
    94             System.out.println(d[i]);
    95         }
    96     }
    97 }
  • 相关阅读:
    个人项目(Word Count Java)
    自我介绍+软工5问
    第六次实践
    第五次实践作业
    第四次实践作业
    第三次实践作业
    第二次实践作业
    第1次实践作业
    第06组 Beta版本演示
    第06组 Beta冲刺(4/4)
  • 原文地址:https://www.cnblogs.com/ylxn/p/12263557.html
Copyright © 2011-2022 走看看