最短路模板 —— Bellman_Ford

时间复杂度对比:
Dijkstra: O ( n 2 ) O(n^2) O(n2)
Dijkstra + 优先队列(堆优化): O ( 2 ∗ E + V ∗ l o g V ) O(2*E+V*logV) O(2E+VlogV)
SPFA: O ( k ∗ E ) O(k*E) O(kE) k k k为每个节点进入队列的次数,一般小于等于 2 2 2,最坏情况为 O ( V ∗ E ) O(V*E) O(VE)
BellmanFord: O ( V ∗ E ) O(V*E) O(VE),可检测负圈
Floyd: O ( n 3 ) O(n^3) O(n3),计算每对节点之间的最短路径

结论:

① ① 当权值为非负时,用Dijkstra。
② ② 当权值有负值,且没有负圈,则用SPFA,SPFA能检测负圈,但是不能输出负圈。
③ ③ 当权值有负值,而且可能存在负圈,则用BellmanFord,能够检测并输出负圈。
④ ④ SPFA检测负环:当存在一个点入队大于等于V次时,则有负环。

P S PS PS:优先队列和SPFA都有可能被题目卡数据 . . . . . . ...... ......


Bellman_Ford:

#include<bits/stdc++.h>
using namespace std;

const int MAX = 0x3f3f3f3f;
const int N = 1010;
int n, m, st; //点,边,起点

typedef struct Edge { //边
	int u, v;
	int w;
} Edge;

Edge edge[N];
int dis[N], pre[N];

bool Bellman_Ford() {
	for(int i=1; i<=n; ++i) //初始化
		dis[i] = (i == st ? 0 : MAX);
	for(int i=1; i<=n-1; ++i){
		bool flag = false;
		for(int j = 1; j <= m; ++j)
			if(dis[edge[j].v] > dis[edge[j].u] + edge[j].w) { //松弛(顺序一定不能反~)
				dis[edge[j].v] = dis[edge[j].u] + edge[j].w;
				pre[edge[j].v] = edge[j].u;
				flag = true;
			}
		if(!flag) return true;//没有负环回路
	}
		
	bool flag = 1; //判断是否含有负权回路
	for(int i=1; i<=m; ++i)
		if(dis[edge[i].v] > dis[edge[i].u] + edge[i].w) {
			flag = 0;
			break;
		}
	return flag;
}

void print_path(int end) { //打印最短路的路径
	stack <int> path;
	int now = end;
	while(1) { //前驱
		path.push(now);
		if(now == st) break;
		now = pre[now];
	}
	while(!path.empty()) {
		now = path.top();
		path.pop();
		if(path.empty()) printf("%d\n", now);
		else printf("%d-->", now);
	}
}

int main() {
	scanf("%d%d%d", &n, &m, &st);
	pre[st] = st;
	for(int i=1; i<=m; ++i)
		scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
	if(Bellman_Ford())
		for(int i = 1; i <= n; ++i) { //每个点最短路
			printf("%d\n", dis[i]);
			printf("Path:");
			print_path(i);
		}
	else printf("have circle!\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值