1. 程式人生 > >單源最短路 SPFA 演算法模板

單源最短路 SPFA 演算法模板

簡介

  • 在圖論中,最短路是十分重要的一部分,在很多問題中都有涉及

  • 而現在所講的 SPFA 演算法是十分優秀的演算法,時間複雜度為 O(kE)

  • 其中 E 是圖的邊數,而 k 是一個常數,一般極小。

  • 事實上 SPFA 就是在 Bellman-ford 演算法的基礎上加上一個佇列優化,減少了冗餘的鬆弛操作,是一種高效的最短路演算法。

  • 而且 SPFA 還能判負環,這種情況下類似 Dijkstra 演算法等便沒有了用武之地!

用法

  • 在佇列中進行,在點出隊入隊中更新值

  • SPFA演算法(BFS)模板如下:

void spfa_bfs(int st)
{
    memset(dis,60,sizeof(dis));
    memset(bz,false
,sizeof(bz)); int l=0,r=1; dis[que[1]=st]=0; while(l<r) { int now=que[++l]; bz[now]=false; for(int i=first[now];i;i=next[i]) if(dis[now]+w[i]<dis[en[i]]) { dis[en[i]]=dis[now]+w[i]; if(!bz[en[i]]) bz[que[++r]=en[i]]=true
; } } return false; }
  • 註釋:其中 que[] 為佇列,dis[] 為點到源點距離,lr 分別左右指標,bz[] 為標誌->點是否入隊。

  • SPFA演算法(DFS)模板如下:

void spfa_dfs(int x)
{
    bz[x]=true;
    for(int i=first[x];i;i=next[i])
        if(dis[now]+w[i]<dis[en[i]])
        {
            dis[en[i]]=dis[now]+w[i];
            if
(!bz[en[i]]]) spfa(en[i]); } bz[x]=false; }

判負環

  • SPFA演算法還有一個大優點是可以判負環

  • 利用 SPFA 演算法判斷負環有兩種方法:

    1. SPFA演算法 的 dfs 形式,判斷條件是 存在一點在一條路徑上出現多次
    2. SPFA演算法 的 bfs 形式,判斷條件是 存在一點入隊次數大於總頂點數

總結

  • SPFA演算法效率高,實用性強,是很有用的演算法!