当负权值存在时,最短路不一定存在,但还是有办法在最短路存在的情况下求出来的。
在介绍之前,需要确定一件事:
如果最短路存在,则一定存在一个不含环的最短路。
理由:
在边权可正可负的图中,环游零环、正环、负环3种。如果包含零环或正环,去掉以后路径不会变长;如果包含负环,则意味着最短路不存在。
既然没有环,最短路最多只经过不含起点在内的n-1个节点,可以通过n-1“轮”松弛操作得到。像如下代码:
for(int i=0; i<n; i++)
{
d[i]=INF;
}
d[0]=0;
for(int k=0; k<n-1; k++)//迭代n-1次
{
for(int i=0; i<m; i++)//检查每条边
{
int x=u[i],y=v[i];
if(d[x]<INF)
{
d[y]=min(d[y],d[x]+w[i]);//松弛操作
}
}
}
上述算法就是Bellman-Ford算法。我们也可以用FIFO队列来代替上面的循环检查。像如下代码:
bool bellman_ford(int s)
{
queue<int> Q;
memset(inq,0,sizeof(inq));
memset(cnt,0,si