[集训笔记4th]带负权图的最短路径专项

B e l l m a n − F o r d Bellman-Ford BellmanFord算法和 S P F A SPFA SPFA算法

dijkstra能应用于带负边权的图,只能用 O ( V E ) O(VE) O(VE)内解决问题的Bellman-ford与spfa算法。

B e l l m a n − F o r d Bellman-Ford BellmanFord

对于给定的一张有向图若对于图中的某一条边 ( x , y , z ) (x,y,z) x,y,z,有dist[y]≤dist[x]+z成立,则称该边满足三角形不等式。若所有边都满足三角形不等式,则dist数组就是各点的最短路径长。
它的流程如下:
1.扫描所有边 ( x , y , z ) (x,y,z) x,y,z,若dist[y]>dist[x]+z,则用dist[x]+z更新dist[y]。
2.重复步骤1,一般n-1遍就可以更新完毕,如果在第n次还有不满足三角形不等式的边,那么就说明有负环出现。

S h o r t e s t P a t h F a s t A l g o r i t h m Shortest Path Fast Algorithm ShortestPathFastAlgorithm

其流程如下:
1.建立一个队列, 最初队列中只含有起点1.
2.取出队头节点下,扫描它的所有出边 ( x , y , z ) (x,y,z) (x,y,z),若dist[y]>dist[x]+z,则使用dist[x]+z去更新 dist[y],同时若y不在队列中,则把y入队(用布尔数组标记)。
3.重复上述步骤,直至队列为空。

void spfa(){
	memset(d, 0x3f, sizeof(d));//dist数组
	memset(v, 0, sizeof(v));//是否在队列中
	d[1] = 0;v[1] = 1;//因为1号点进入了队列
	q.push(1);
	while(q.size()){
	// 取出队头
		int x = q.front();q.pop();
		v[x] = 0;//这时候队头不在队列中,所以记为0
	//扫描所有出边
		for(int i  = head[x]; i; i = Next[i]){
			int y = ver[i], z = edge[i];
			if(d[y] > d[x]+z){
				//更新,把新的二元组插入堆
				d[y] = d[x] + z;
				if(!v[y]) q.push(y), v[y] = 1;
			}
		}
	}
}

无注释版

void spfa(){
	memset(d, 0x3f, sizeof(d));
	memset(v, 0, sizeof(v));
	d[1] = 0;v[1] = 1;
	q.push(1);
	while(q.size()){
		int x = q.front();q.pop();
		v[x] = 0;
		for(int i  = head[x]; i; i = Next[i]){
			int y = ver[i], z = edge[i];
			if(d[y] > d[x]+z){
				d[y] = d[x] + z;
				if(!v[y]) q.push(y), v[y] = 1;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值