題目鏈接: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;
}