是对Bellman-Ford算法的一个优化,用队列来存储那些最短距离发生变化的节点。
Bellman-Ford算法的核心是询问邻居到S的距离,来更新自己到S的距离。
换而言之,只有邻居变化了,我才有可能变化。所以只需要将那些最短距离发生变化的点,放入队列中,更新他的邻居。省去了更新所有节点的操作。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
int Head[N],Value[N],Next[N],Weight[N],Index;//邻接表存储图
bool IsInQueue[N];//判断当前这个点是否在队列中
int n,m;//n个节点 m条边
int Dis[N];//最短距离
//邻接表加边
void AddEdge(int nStart, int nEnd, int nWeight)
{
Value[Index] = nEnd;
Weight[Index] = nWeight;
Next[Index] = Head[nStart];
Head[nStart] = Index;
Index++;
}
void SPFA()
{
//初始化Dis数组
fill(Dis,Dis+N,0x3f3f3f3f);
Dis[1] = 0;
//定义节点变化的队列
queue<int>Queue;
//1号节点入队
Queue.push(1);
//标记为在队列中
IsInQueue[1] = true;
while(Queue.size())
{
int t = Queue.front();
Queue.pop();
IsInQueue[t] = false;
//所有与t相邻的边
for(int i = Head[t]; i != -1; i = Next[i])
{
int j = Value[i];
//如果最短距离发生变化
if(Dis[j] > Dis[t] + Weight[i])
{
Dis[j] = Dis[t] + Weight[i];
if(!IsInQueue[j])
{
Queue.push(j);
IsInQueue[j] = true;
}
}
}
}
}
int main(int argc, char** argv)
{
//读入节点数n 边数m
scanf("%d%d",&n,&m);
//初始化头结点数组
fill(Head, Head+N, -1);
//加边
for(int i = 0; i < m; i++)
{
int nStart,nEnd,nWeight;
scanf("%d%d%d",&nStart, &nEnd, &nWeight);
AddEdge(nStart, nEnd, nWeight);
}
//求取最短距离
SPFA();
//输出
for(int i = 1; i <= n; i++)
{
cout<<Dis[i]<<endl;
}
return 0;
}
本文介绍了如何使用队列优化Bellman-Ford算法,通过仅更新最短路径改变的节点,提高搜索效率,避免了不必要的全图遍历。
758

被折叠的 条评论
为什么被折叠?



