队列优化的Bellman-Ford(贝尔曼-福特)算法
1:在处理单源最短路问题时,如果边出现负数的情况,而因为Dijkstra算法采用的是贪心的思想,所以无法处理负权值的情况。故采用此算法。
2:为了减少时间复杂度,我们采用邻接表储存图,并且采用队列优化来减少不必要的循环。
采用队列优化的理由:如果不进行优化那么外循环需要循环n-1次。而大多数情况下并不需要循环怎么多次。所以我们每次只对最短路估值发生变化的顶点的所有出边执行松弛操作。因为,只有此点的最短路估值发生变化,再去用此点判断其他顶点,才有可能更新最短路径。
#include <stdio.h>
int head,tail,inf,n,m,next[1001],first[1001],u[100],v[100],w[100],que[100],book[100],dis[100];
//next[i]储存顶点u[i]的上一条边的编号,pirst[i]储存输入的最后一条边的编号。dis[i]表示顶点1到顶点i的最短距离。
int main()
{
inf=1e9;
tail=1;
head=1;
scanf("%d%d",&n,&m);
que[head]=1; //将顶点1入队
book[1]=1; //标记那个顶点在队列中。
tail++;
for(int i=1;i<=n;i++)
{
first[i]=-1;//此时没有边
dis[i]=inf;//距离初始化为无穷大
}
dis[1]=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
next[i]=first[u[i]]; //next[i]储存u[i]顶点上一条边的编号
first[u[i]]=i; //first[i]储存u[i]顶点输入的最后一条边的编号
}
int temp=first[que[head]];
while(head<tail)
{
while(temp!=-1)
{
if(dis[v[temp]]>dis[u[temp]]+w[temp])
{
dis[v[temp]]=dis[u[temp]]+w[temp];
if(!book[v[temp]])
{
que[tail++]=v[temp];
book[v[temp]]=1;
}
}
temp=next[temp];
}
book[que[head]]=0;
head++;
temp=first[que[head]];
}
for(int i=1;i<=n;i++)
{
printf("%d\n",dis[i]);
}
return 0;
}