SPFA单源最短路径

来源:互联网 发布:网络选择软件 编辑:程序博客网 时间:2024/04/28 20:40

SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余松弛操作。前面说的Dijkstra算法虽然思想简单,优化也不难,但是如果面对含有负环的图来求解的话就无能为力了。并且从另一方面讲,即使图中没有负环,由于Dijkstra算法是基于结点的,而SPFA算法是基于边数的,所以说对于结点较少而边数较多(也就是稠密图)来说,无疑PriorityQueue+Dijkstra是最好的选择;而对于结点较多边数较少(也就是稀疏图)来说无疑SPFA最高效。


简单提一下SPFA算法思想:Bellman-Ford的升级版,使用一个队列来维护松弛过的结点,初始时将源节点加入队列,之后每次对队列进行出队列操作,并将出队列的这个结点对它的所有邻接节点进行松弛操作,并将松弛成功的结点加入到队列中(如果在队列中就不再添加),重复以上操作直到队列为空。另外判断图中是否存在负环:如果某一个结点进队列次数超过了n就说明存在负环。


对于稀疏图来说,SPFA的效率比PriorityQueue+Dijkstra的效率还略高,实现却比后者简单了许多。


实例:蓝桥杯ALGO-5"最短路"


算法训练 最短路  
时间限制:1.0s   内存限制:256.0MB
      
问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定

对于10%的数据,n = 2,m = 2。

对于30%的数据,n <= 5,m <= 10。

对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。


SPFA算法实现代码:


import java.util.HashMap;import java.util.Iterator;import java.util.PriorityQueue;import java.util.Queue;import java.util.Scanner;import java.util.Set;public class Spfa {static int nodeCount;static int edgeCount;static Node[] nodeArray;static int [] dist;static Queue<Integer> queue;static int max = 10000000;static class Node {private HashMap<Integer, Integer> map = null;public void addEdge(int end, int edge) {if (this.map == null) {this.map = new HashMap<Integer, Integer>();}this.map.put(end, edge);}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);nodeCount = sc.nextInt();edgeCount = sc.nextInt();queue = new PriorityQueue<Integer>();dist = new int[nodeCount + 1];nodeArray = new Node[nodeCount + 1];// nodeArray初始化for (int i = 0; i < nodeCount + 1; i ++) {nodeArray[i] = new Node();dist[i] = max;}dist[1] = 0;for (int i = 0; i < edgeCount; i ++) {int begin = sc.nextInt();int end = sc.nextInt();int edge = sc.nextInt();nodeArray[begin].addEdge(end, edge);}sc.close();long begin = System.currentTimeMillis();spfa();for (int i = 2; i < nodeCount + 1; i ++) {System.out.println(dist[i]);}long end = System.currentTimeMillis();System.out.println(end - begin + "ms");}private static void spfa() {queue.offer(1);while (!queue.isEmpty()) {int index = queue.poll();HashMap<Integer, Integer> hm = nodeArray[index].map;if (hm == null) {continue;}Set<Integer> s = hm.keySet();Iterator<Integer> it = s.iterator();while (it.hasNext()) {int num = it.next();if (dist[index] + hm.get(num) < dist[num]) {dist[num] = dist[index] + hm.get(num);if (!queue.contains(num)) {queue.offer(num);}}}}}}



1 0
原创粉丝点击