Bellman-Ford算法
作用:求源点到其他所有点的最短路径,可以处理存在负环的情况
时间复杂度:O(V*E) //V为顶点数,E为边数
原理:
1.用Distans[i]记录源点s到i的距离,首先初始化Distanc,如果存在s到i的边则设Distans[i]=si,如果不存在,则设Distans[i]=无穷,Distans[s]=0。
2.对于n个顶点中的每个顶点u,检测其对于每一条边uv,Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值。
3.为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。
c代码实现
#include<stdio.h>
#include<stdlib.h>
const int maxnum = 100;
const int maxint = 99999;
// 边
typedef struct Edge{
int u, v; // 起点,终点点
int weight; // 边的权值
}Edge;
Edge edge[maxnum]; // 保存所有边的值
int dist[maxnum]; // 结点到源点最小距离
int nodenum, edgenum, source; // 结点数,边数,源点
void init()
{
// 输入结点数,边数,源点
scanf("%d%d%d",&nodenum,&edgenum,&source);
for(int i=1; i<=nodenum; ++i)
dist[i] = maxint;
dist[source] = 0;
for(int i=1; i<=edgenum; ++i)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].weight);
if(edge[i].u == source) //注意这里设置初始情况
dist[edge[i].v] = edge[i].weight;
}
}
// 松弛计算
void relax(int u, int v, int weight)
{
if(dist[v] > dist[u] + weight)
dist[v] = dist[u] + weight;
}
bool Bellman_Ford()
{
for(int i=1; i<=nodenum-1; ++i)
for(int j=1; j<=edgenum; ++j)
relax(edge[j].u, edge[j].v, edge[j].weight);
bool flag = 1;
// 判断是否有负环路
for(int i=1; i<=edgenum; ++i)
if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)
{
flag = 0;
break;
}
return flag;
}
int main(){
init();
if(Bellman_Ford())
for(int i = 1 ;i <= nodenum; i++)
printf("%d\n",dist[i]);
return 0;
}