演算法筆記_071:SPFA演算法簡單介紹(Java)

來源:互聯網
上載者:User

標籤:組隊   article   images   url   while   lis   複雜   距離   輸入   

目錄

1 問題描述

2 解決方案

2.1 具體編碼

  1 問題描述

何為spfa(Shortest Path Faster Algorithm)演算法?

spfa演算法功能:給定一個加權連通圖,選取一個頂點,稱為起點,求取起點到其它所有頂點之間的最短距離,其顯著特點是可以求含負權圖的單源最短路徑,且效率較高。(PS:引用自百度百科:spfa是求單源最短路徑的一種演算法,它還有一個重要的功能是判負環(在差分約束系統中會得以體現),在Bellman-ford演算法的基礎上加上一個隊列最佳化,減少了冗餘的鬆弛操作,是一種高效的最短路演算法。)

spfa演算法思想:spfa就是BellmanFord的一種實現方式,其具體不同在於,對於處理鬆弛操作時,採用了隊列(先進先出方式)操作,從而大大提高了時間複雜度。 (PS:對於BellmanFord演算法可以參考本人的另一篇文章演算法筆記_070:BellmanFord演算法簡單介紹(Java))

 

 

 

2 解決方案 2.1 具體編碼

spfa演算法尋找單源最短路徑的時間複雜度為O(m*E)。(其中m為所有頂點進隊的平均次數,可以證明m一般小於等於2*圖頂點個數,E為給定圖的邊集合)

首先看下代碼中所使用的連通圖(PS:改圖為無向連通圖,所以每兩個頂點之間均有兩條邊):

 

現在求取中頂點B到其它所有頂點之間的最短距離。

具體代碼如下:

package com.liuzhen.chapter9;import java.util.ArrayList;import java.util.Scanner;public class Spfa {        public long[] result;         //用於得到第s個頂點到其它頂點之間的最短距離        //內部類,用於存放圖的具體邊資料    class edge {        public int a;  //邊的起點        public int b;  //邊的終點        public int value;   //邊的權值                edge(int a, int b, int value) {            this.a = a;            this.b = b;            this.value = value;        }    }    /*     * 參數n:給定圖的頂點個數     * 參數s:求取第s個頂點到其它所有頂點之間的最短距離     * 參數edge:給定圖的具體邊     * 函數功能:如果給定圖不含負權迴路,則可以得到最終結果,如果含有負權迴路,則不能得到最終結果     */    public boolean getShortestPaths(int n, int s, edge[] A) {        ArrayList<Integer> list = new ArrayList<Integer>();        result = new long[n];        boolean[] used = new boolean[n];        int[] num = new int[n];        for(int i = 0;i < n;i++) {            result[i] = Integer.MAX_VALUE;            used[i] = false;        }        result[s] = 0;     //第s個頂點到自身距離為0        used[s] = true;    //表示第s個頂點進入數組隊        num[s] = 1;       //表示第s個頂點已被遍曆一次        list.add(s);      //第s個頂點入隊        while(list.size() != 0) {            int a = list.get(0);   //擷取數組隊中第一個元素            list.remove(0);         //刪除數組隊中第一個元素            for(int i = 0;i < A.length;i++) {                //當list數組隊的第一個元素等於邊A[i]的起點時                if(a == A[i].a && result[A[i].b] > result[A[i].a] + A[i].value) {                     result[A[i].b] = result[A[i].a] + A[i].value;                    if(!used[A[i].b]) {                        list.add(A[i].b);                        num[A[i].b]++;                        if(num[A[i].b] > n)                            return false;                        used[A[i].b] = true;   //表示邊A[i]的終點b已進入數組隊                    }                }            }            used[a] = false;        //頂點a出數組對        }        return true;    }        public static void main(String[] args) {        Spfa test = new Spfa();        Scanner in = new Scanner(System.in);        System.out.println("請輸入一個圖的頂點總數n起點下標s和邊總數p:");        int n = in.nextInt();        int s = in.nextInt();        int p = in.nextInt();                edge[] A = new edge[p];        System.out.println("請輸入具體邊的資料:");        for(int i = 0;i < p;i++) {             int a = in.nextInt();             int b = in.nextInt();             int value = in.nextInt();             A[i] = test.new edge(a, b, value);        }        if(test.getShortestPaths(n, s, A)) {             for(int i = 0;i < test.result.length;i++)                 System.out.print(test.result[i]+" ");        } else             System.out.println("給定圖存在負環,沒有最短距離");    }}

運行結果:

請輸入一個圖的頂點總數n起點下標s和邊總數p:6 1 18請輸入具體邊的資料:0 1 60 2 31 2 21 3 52 3 32 4 43 4 23 5 34 5 51 0 62 0 32 1 23 1 53 2 34 2 44 3 25 3 35 4 55 0 2 5 6 8 

 

 

參考資料:

1. SPFA演算法詳解

 

演算法筆記_071:SPFA演算法簡單介紹(Java)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.