Bellman-Ford
date: 2018/2/2
author:pprp
theme:Dijstra
简介
- 单源最短路问题
- 要求: 图中不能出现负圈
- 思路:
Bellman-Ford算法就是遍历所有的边进行\(n-1\)次更新(每次更新就是对所有的可用节点进行松弛)
- 对比:Dijkstra算法:重复比较多,对每个都要进行松弛,这事实上是没有必要的,但是也是可以保证结果的准确性
代码实现
#include <iostream>
using namespace std;
const int MAX_E = 1000;
const int MAX_V = 1000;
const int inf = 0x3f3f3f3f;
struct edge{
int from;
int to;
int cost;
};
edge es[MAX_E];
int d[MAX_V];
int V, E;
void shortest_path(int s){
for(int i = 0 ; i < V; i++){
d[i] = inf;
}
d[s] = 0;
while(true){
bool update = false;
for(int i = 0 ; i < E; i++){
edge e = es[i];
if(d[e.from] != inf && d[e.to] > d[e.from] + e.cost){
d[e.to] = d[e.from] + e.cost;
update = true;
}
}
if(!update)break;
}
}
int main() {
cin >> V >> E;
int x, y, z;
for(int i = 0 ; i < E; i++){
cin >> es[i].from >> es[i].to >> es[i].cost;
}
shortest_path(0);
for(int i = 0 ; i < V; i++){
cout << d[i] << " ";
}
cout << endl;
return 0;
}
clear all;close all;clc
%初始化邻接压缩表
b=[1 2 6;
4 7
3 5;
4 8;
5 -4;
2 -2;
3 -3;
5 9;
1 2;
3 7];
m=max(max(b(:,1:2))); %压缩表中最大值就是邻接矩阵的宽与高
A=compresstable2matrix(b); %从邻接压缩表构造图的矩阵表示
netplot(A,1) %形象表示
S=inf(1,m); %源到其他节点的最短距离,开始为inf
S(1)=0; %源点到自己的距离为0
pa=zeros(1,m); %寻找到的节点的前趋
pa(1)=1; %源点的前趋是自己
pre_pa=ones(1,m);
while sum(pre_pa==pa)~=m %终止条件,判断终止的方法很多,这个应该不是最佳实践
pre_pa=pa;
for k=1:m
if pre_pa(k)~=0 %对每一个已搜寻到的节点,从此节点寻找后继节点
i=k;
for j=1:m
if A(i,j)~=inf
if S(j)>S(i)+A(i,j)
S(j)=S(i)+A(i,j); %边缘松弛,取两节点间最小权值作为实际权值
pa(j)=i; %寻找前趋
end
end
end
end
end
end
%最终我们需要的就是这两个值
S %源点到其他每一点的距离
pa %其他每一节点的前趋
%算法到此结束,下面只是为了形象的表示而写的。
re=[];
for i=2:m
re=[re;pa(i) i A(pa(i),i)];
end
A=compresstable2matrix(re); %从邻接压缩表构造图的矩阵表示
figure;
netplot(A,1) %形象表示
function A=compresstable2matrix(b)
[n ~]=size(b);
m=max(max(b(:,1:2)));
A=inf(m,m);
for i=1:n
A(b(i,1),b(i,2))=b(i,3);
end
end