Dijkstra算法的局限性:不能处理权值为负值的情形,Dijkstra算法在利用顶点u的dist[ ]值递推各顶点的dist[ ]值时,前提是顶点u的dist[ ]值是当前最短路径长度最小的,如果图中所有边的权值都是正的,这样推导没有问题,但如果有负权值的边,这样推导就不正确。
Bellman-Ford算法思想:从源点逐次途经其他顶点,以缩短到达终点的最短路径 长度。
限制条件:要求图中不能包含权值总和为负值的回路。
例题:求顶点0到其他各顶点的最短路径长度,并输出对应的最短路径
#include <cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxint 0x3f3f3f3f
void Bellman(int v0);
int map[110][110];
int dist[110];
int path[110];
int n;
int main()
{
int u,v,w;
scanf("%d",&n);
memset(map,maxint,sizeof(map));
while(1)
{
scanf("%d%d%d",&u,&v,&w);
if(u==-1&&v==-1&&w==-1) break;
map[u][v]=w;
}
for(int i=0;i<n;i++)///如果i==j,map[i][j]=0;
for(int j=0;j<n;j++)
if(i==j)
map[i][j]=0;
Bellman(0);
int shortest[110];
for(int i=1;i<n;i++)
{
printf("%d\t",dist[i]);
memset(shortest,0,sizeof(shortest));
int k=0;
shortest[k]=i;
while(path[shortest[k]]!=0)
{
k++;
shortest[k]=path[shortest[k-1]];
}
k++;
shortest[k]=0;
for(int i=k;i>0;i--)
printf("%d-",shortest[i]);
printf("%d\n",shortest[0]);
}
}
void Bellman(int v0)
{
for(int i=0;i<n;i++)
{
dist[i]=map[v0][i];
if(i!=v0&&dist[i]<maxint)
path[i]=v0;
else
path[i]=-1;
}
for(int k=2;k<n;k++)///k表示:从源点v0出发最多不经过k条边到达终点u
for(int u=0;u<n;u++) ///u表示终点,修改每个顶点的dist[u]和path[u]
if(u!=v0)
{
for(int j=0;j<n;j++)///考虑其他每个顶点
if(map[j][u]<maxint&&dist[j]+map[j][u]<dist[u])
{
dist[u]=dist[j]+map[j][u];
path[u]=j;
}
}
}