SPFA 算法

/**
    SPFA: Shortest Path Faster Algorithm
    看到名字不禁爲之一顫,SPFA算法是西南交通大學段凡丁於1994年發表的。
    SPFA 也是競賽中最常見的算法之一,不僅僅用來解決帶負權的單源最短路
    而且是求解差分約束問題的專用算法,也常用它和最大流合作解決最小費問題
    可以說SPFA 是 dijkstra 和 bellman 的結合體,功能可見一斑……

    SPFA 算法的最壞複雜度爲 O(2*E)。。

    SPFA 和dijkstra 格式很接近,只是加了個隊列或棧就變得無比神奇了。

    這裏用鄰接表形式寫下spfa 的模板

    後面再介紹它的其它功能,這裏只知道它和bellman 功能一樣,僅僅快即可
*/

const int inf = 0x3f3f3f3f;
const int nMax = 1000;
const int eMax = 500000;

struct {
    int v, w, next;
}edge[eMax];

int edgeHead[nMax], dis[nMax], n, ne; //n爲點的個數, ne添邊所用 //初始化edgeHead = 0 ne > 0
int vis[nMax], queue[nMax]; /**  stack[nMax] */  //替換queue

void addEdge(int u, int v, int w) {
    edge[ne].v = v;
    edge[ne].w = w;
    edge[ne].next = edgeHead[u];
    edgeHead[u] = ne++;
}

int spfa(int s, int t) {
    int i, head=0, tail=1 ; /** top = 0 */      //替換head , tail
    for (i=0; i<=n; i++) {
        dis[i] = inf;
        vis[i] = false;
    }
    dis[s] = 0;
    queue[0] = s;

    while (tail != head) {     /** (top) */   //替換(tail != head)
        int u = queue[head++]; /** u = stack[top--] */ //替換
        vis[u] = true;    //這裏可有可無……
        for (i=edgeHead[u]; i; i=edge[i].next) {
            int v = edge[i].v, w = edge[i].w;
            if (dis[v] > dis[u]+w) {
                dis[v] = dis[u] + w;
                if (!vis[v]) {
                    vis[v] = true;
                    /******************/
                    queue[tail++] = v;
                    if (tail == nMax) //循環隊列
                        tail = 0;
                    /** stack[++top] = v */  //替換
                }
            }
        }
        vis[u] = false;    //這裏是必須得有
        /****************/
        if (head == nMax)  //stack不需要噢,循環隊列

            head = 0;
        /****************/   //替換刪除
    }

    return dis[t];
}

/**
    注意: 添邊時初始化 edgeHead = 0, ne > 0
          將標有替換的地方替換則變爲棧操作
    判斷正負權迴路時,如果某點進入隊列或棧的次數超過n 次則存在環
    只需用cnt[nMax] 數組標記每個點進入隊列次數即可

    超級注意,只所以提供隊列和棧兩種操作是因爲有些題卡隊列,有些題卡堆棧
    不過肯定有一種能過,這種情況經常遇到,要注意啊!!!!!!!!!!!!
*/

收藏於 2011-11-25
來自於百度空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章