Ballman-Ford的最短路径算法是以边为单位进行的,而Dijkstra则是以顶点为单位进行的啦。
Ballman-Ford算法需要遍历所有|E|条边,最坏的情况下需要遍历|V – 1|*|E|条边,所以可以借助这个特点来判断图是否有负圈哦。
Ballman-Ford能够解决带有负圈的图。
时间复杂度为O(|E|*|V|)。
#include <stdio.h>
#include <string.h>
#define MAX_E 501
#define MAX_V 1001
#define INF 0xffffff
struct edge {
int from, to;
int cost;
};
edge e[MAX_E];
int lowcost[MAX_V];
int eCnt, vCnt;
int start, end;
void bellman(int s) {
int i;
bool update;
for (i = 0; i <= vCnt; i++) {
lowcost[i] = INF;
}
lowcost[s] = 0;
while (true) {
update = false;
for (i = 0; i < eCnt; i++) {
if (lowcost[e[i].to] > lowcost[e[i].from] + e[i].cost) {
lowcost[e[i].to] = lowcost[e[i].from] + e[i].cost;
update = true;
}
}
if (!update) {
break ;
}
}
}
bool findNegativeLoop() {
int i, j;
memset(lowcost, 0, sizeof(lowcost));
for (i = 0; i < vCnt; i++) {
for (j = 0; j < eCnt; j++) {
if (lowcost[e[i].to] > lowcost[e[i].from] + e[i].cost) {
lowcost[e[i].to] = lowcost[e[i].from] + e[i].cost;
if (i == vCnt - 1) {
return true;
}
}
}
}
return false;
}
int main() {
int i;
printf("依次输入有向图{顶点数, 边数, 起点, 终点, 边(from, to, cost)}:\n");
while (true) {
scanf("%d%d%d%d", &vCnt, &eCnt, &start, &end);
for (i = 0; i < eCnt; i++) {
scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].cost);
}
if (findNegativeLoop()) {
printf("有负圈存在\n");
} else {
printf("无负圈存在\n");
}
bellman(start);
printf("lowcost = %d\n", lowcost[end]);
}
return 0;
}
5 7 1 4
1 2 3
1 3 6
1 5 2
2 3 2
2 5 4
2 4 6
5 4 5
5 7 1 3
1 2 3
1 3 6
1 5 2
2 3 -1
2 5 4
2 4 6
5 4 5
5 7 1 4
1 2 -1
1 3 -4
1 5 -2
2 3 -3
2 5 -5
2 4 -6
5 4 -1