一、问题描述
Dijkstra算法虽然是好的,但是不能解决负权边问题(边的权值是负数)。
要解决负权边问题,这里介绍一种在思想上和代码上都完美的最短路算法,这个算法就是Bellman-Ford.
二、思路解析及算法介绍
1.该算法核心代码只有4行。(代码中的“松弛”操作与Dijkstra算法的松弛操作是一样的)
//四行核心代码
//n 是顶点的个数,m是边的个数
//dis[] 数组用来记录源点到其余各个顶点的最短路径
for(k=1;k<=n-1;k++)
for(i=1;i<=m;i++)
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]]=dis[u[i]]+w[i];
三、代码复现
#include<stdio.h>
int main(){
int dis[10],i,k,n,m,u[10],v[10],w[10];
int inf=99999999;//存储一个我们认为的正无穷值
//读入n和m,n表示顶点数目,m表示边的数目
scanf("%d %d",&n,&m);
//读入边
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&u[i],&v[i],&w[i]);
}
//初始化dist数组
//这里是1号顶点到其余各个顶点的初始路程
for(i=1;i<=n;i++)
dis[i]=inf;
dis[1]=0;
//四行核心代码
//n 是顶点的个数,m是边的个数
//dis[] 数组用来记录源点到其余各个顶点的最短路径
for(k=1;k<=n-1;k++)
for(i=1;i<=m;i++)
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]]=dis[u[i]]+w[i];
//输出最终结果
for(i=1;i<=n;i++)
printf("%d ",dis[i]);
getchar();
getchar();
return 0;
}
四、总结
1.最短路径肯定是一个不包含回路的简单路径。
路径分为回权正路(即回路权值之和是正)和回权负路(即回路权值之和是负)。这两种回路都是不可能有的。
2.该算法还可以检测一个图中是否包含负权回路。
3.该算法的时间复杂度是O(MN),我们可以对其进行优化操作。优化方式可以有几种?
获取我们会在下一期见分晓!