来源自我的博客
http://www.yingzinanfei.com/2017/04/07/bellman-fordsuanfaheduilieyouhuaspfaqiudanyuanzuiduanlujing/
#include <stdio.h>
#include <limits.h>
int main(){
int n, m;
scanf("%d%d", &n, &m);
int u[10], v[10], w[10]; // 分别表示边的两顶点编号和权值
for (int i = 1; i <= m; i++){
scanf("%d%d%d", &u[i], &v[i], &w[i]);
}
int dis[10]; // 源点到任意点的距离
for (int i = 1; i <= n; i++){
dis[i] = INT_MAX;
}
dis[1] = 0;
int bak[i];
// 核心语句,循环n-1次
for (int k = 1; k <= n - 1; k++){
// 备份距离数组以检测是否已完成
for (int i = 1; i <= n; i++) bak[i] = dis[i];
// 每次循环遍历所有边
for (int i = 1; i <= m; i++){
// 判断源点到点v[i]距离能不能通过走源点->点u[i]->点v[i]的路线更短
if (dis[v[i]] > dis[u[i]] + w[i]){
dis[v[i]] = dis[u[i]] + w[i];
}
}
// 循环完检测当前dis是否有更新
bool check = 0;
for (int i = 1; i <= n; i++) {
if (bak[i] != dis[i]) {
check = 1;
break;
}
}
if (check = 0) break; // 如果 dis数组没更新,提前退出循环
}
// 检测负权回路
bool flag = 0;
for (int i = 1; i <= m; i++){
if (dis[v[i]] > dis[u[i]] + w[i]) flag = 1;
}
if (flag == 1) printf("有负权回路\n");
// 输出最终结果
for (int i = 1; i <= n; i++){
printf("%d ", dis[i]);
}
return 0;
}
// 队列优化的Bellman-Ford算法(SPFA算法)
#include <iostream>
#include <climits>
#include <queue>
#include <vector>
using namespace std;
int main(){
int n, m;
cin >> n >> m;
vector <int> dis(n, INT_MAX); // 源点到每个点的距离
dis[0] = 0;
vector <int> first(n, -1); // 每个结点相邻的边中第一条边的编号,-1表示没有相邻的边
vector <int> next(m, -1); // 每条边的下一条边的编号
vector <bool> book(n, false); // true表示在队列中
vector <int> u(m), v(m), w(m); // 每条边的两顶点和权值
// 建立邻接表
for (int i = 0; i < m; i++){
cin >> u[i] >> v[i] >> w[i];
// 将新边头插到邻接表中
next[i] = first[u[i]]; // 此边的下一边为u[i]起头的第一条边
first[u[i]] = i; // 将此边作为u[i]起头的第一条边
}
queue <int> Q;
// 将源点入队列
Q.push(0);
book[0] = true;
// 队列不空时循环
while (!Q.empty()){
// 取队首
int k = first[Q.front()]; // k表示队首点的第一条邻接边的编号
// 扫描队首顶点所有的邻边
while (k != -1){
// 判断源点到点v[k]的距离能不能通过源点->点u[k]->点v[k]来更新
if (dis[v[k]] > dis[u[k]] + w[k]){
dis[v[k]] = dis[u[k]] + w[k];
// 判断点v[k]在不在队列中
if (book[v[k]] == false){
// 不在队列中则入队
Q.push(v[k]);
book[v[k]] = true;
}
}
// k移向下一条邻接边
k = next[k];
}
// 队首结点用完了,可以出队了
book[Q.front()] = false;
Q.pop();
}
// 输出源点到其余各个顶点的最短路径
for (int i = 0; i < n; i++){
cout << dis[i] << " ";
}
cout << endl;
return 0;
}