單源最短路-SPFA(poj2387)

題目鏈接:http://poj.org/problem?id=2387

1.用鄰接表存圖
用u[i],v[i],w[i]數組表示第i條邊是從點u[i]到v[i],路徑長度是w[i];
用first[i]數組存頂點i的第一條邊的編號;
用next[i]數組存第i條邊的下一條邊的編號;
2.用dis[i]數組表示從源點到i點的最短路徑;
3.用book[i]數組標記點i是否在隊列中;

SPFA算法步驟:
1.初始時將源點加入隊列
2.每次從隊首取出一個頂點,對這個頂點的所有出邊進行鬆弛操作,若鬆弛成功,這個出邊指向的頂點入隊,對當前頂點處理完後出隊
3.重複第2步直到隊列爲空

算法複雜度:最壞O(N*M)

#include <iostream>

using namespace std;

int u[4005],v[4005],w[4005]; //鄰接表存圖
int first[1005];  //點i的第一條邊的編號
int ne[4005]; // 邊i的下一條邊
int dis[1005],book[1005];
int que[9999999],head = 1,tail = 1; //定義隊列並初始化
int inf = 99999999;

int main()
{
    int t,n;
    cin>>t>>n;

    // 初始化dis數組 ,表示1號頂點到其餘各個頂點的路程
    for (int i =1; i <= n; i++)
        dis[i] = inf;
    dis[1] = 0;

    //初始化book數組,一開始所有頂點都不在隊列中
    for (int i =1; i<= n; i++)
        book[i] = 0;

    //初始化first數組,next數組,表示頂點暫時都沒有邊
    for(int i =1;i <= n;i++)
    {
        first[i] = -1;
    }
    //讀入邊,建立鄰接表
    for (int i =1; i <= 2*t; i++)
    {
        cin>>u[i]>>v[i]>>w[i];
        ne[i] = first[u[i]];
        first[u[i]] = i;
        i++;
        u[i] = v[i - 1];
        v[i] = u[i - 1];
        w[i] = w[i - 1];
        ne[i] = first[u[i]];
        first[u[i]] = i;
    }

    //1號頂點入隊
    que[tail] = 1;
    tail++;
    book[1] = 1;

    while (head<tail)   //隊列不爲空時循環
    {
        int k = first[que[head]];
        while (k != -1)
        {
            if (dis[v[k]] > dis[u[k]] + w[k])
            {
                dis[v[k]] = dis[u[k]] + w[k];
                if (book[v[k]] == 0 )
                {
                    que[tail] = v[k];
                    tail++;
                    book[v[k]] = 1;
                }
            }
            k = ne[k];
        }
        book[que[head]] = 0;
        head++;
    }

    cout<<dis[n]<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章