【最短路徑】 SPFA算法


  上一期介紹到了SPFA算法,只是一筆帶過,這一期讓我們詳細的介紹一下SPFA。

1 SPFA原理介紹

  SPFA算法和dijkstra算法特別像,總感覺自己講的不行,同學說我的博客很辣雞,推薦一個視頻講解,想看點這里,算法思路如下:

  1)和dijkstra一樣初始化,定義一個dis[ ]數組,除了源點賦成0之外其它點都賦成正無窮,然后定義一個隊列q。

  2)把隊列q的隊首元素取出,標志為不在隊中,將其作為中繼點對這個隊首元素的所有出邊進行松弛操作(不知道松弛操作請看這里),修改完dis值后,判斷每一個修改過dis值的元素是否在隊列q中,如果不在,就放入隊尾;然后判斷這個數入隊的次數,如果大於n(n為點的個數),那就說明出現了負權回路,算法結束,否則繼續。

  3)不斷循環,直到隊列為空。

2 實現過程中的一些問題

  •   question:怎么標志出隊?

  answer:可以定義一個vis[ ]數組,最開始全部為0,表示都不在隊列中,每入隊一個元素x,就把vis[x]賦成1,每出隊一個元素就賦值成0。

  •   question:怎么判斷一個數入隊次數?

  answer:可以定義一個num[ ]數組,每入隊一個元素x,就num[x]++;這個可以不寫,因為題目一般不會出現負權回路。

  •   question:怎么判斷隊列為空?

  answer:最流行的寫法是while(!q.empty()),但是不太好理解,我一般會寫成while(s.size()),和前一句意思相同。

3 圖解演示

  //這個圖解做了一上午,可能講的不好,不喜勿噴

4 代碼奉上:

 1 void SPFA()
 2 {
 3     for(int i=1;i<=n;i++)
 4     dis[i]=inf;
 5     queue<int>q;
 6     q.push(1);vis[1]=1;dis[1]=0;
 7     while(q.size())
 8     {
 9         x=q.front();q.pop();vis[x]=0;
10         for(int i=head[x];i;i=a[i].next)
11         {
12             int s=a[i].to;
13             if(dis[s]>dis[x]+a[i].cost)
14             {
15                 dis[s]=dis[x]+a[i].cost;
16                 if(vis[s]==0)
17                 {
18                     vis[s]=1;
19                     q.push(s);
20                 }
21             }
22         }
23     }
24 }

 5 算法優化

  新更博客:SPFA算法優化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM