Bellman-Ford

Bellman-Ford

  • 本质:DP,对边进行操作

  • 特点:单源最短路,求解一个源点到其他所有点的最短距离

  • 适用对象:小图,允许负权图和负环图(负环:图上边权之和为负的环)

  • 存储结构:直接存边

  • 核心思想:反复松弛所有边(最多进行 V − 1 V-1 V1轮),若该边使距离更优则更新

  • 算法流程:闫氏DP分析法

    • 状态表示:
      • 集合:定义源点 s s s到每个顶点的最短路长度 d i s dis dis(初始化为 + ∞ +\infty +表示该点不可达,源点初始化为0),路径数组 p a t h path path(存储其上一个来源顶点,初始化为 − 1 -1 1表示无路径)
      • 属性: M i n Min Min
    • 状态计算:设当前边为 < u , v > <u,v> <u,v>,循环执行下列步骤,直到循环 V − 1 V-1 V1轮或没有结点 d i s dis dis再更新(若循环超过 V − 1 V-1 V1轮还在更新说明存在负环)
      • 不选第 k k k条边:若选当前边不能使边的终点 v v v到源点 s s s的距离减小,则不选该边。 d i s [ v ] dis[v] dis[v]不变。
      • 选第 k k k条边:若选当前边能够使边的终点 v v v到源点 s s s的距离减小,则选该边。 d i s [ v ] = d i s [ u ] + w dis[v]=dis[u]+w dis[v]=dis[u]+w。(该边被松弛)
    • 状态转移方程式: d i s [ v ] = m i n ( d i s [ v ] , d i s [ u ] + w ) dis[v]=min(dis[v],dis[u]+w) dis[v]=min(dis[v],dis[u]+w)
      实际上,此处默认运用了滚动数组压到了一维。
  • 复杂度: O ( V E ) O(VE) O(VE)

  • 与Dijkstra算法的区别:

    1. Dijkstra每次考查的是先前未被考察且 d i s dis dis最小的点,一旦被考查后其将不再被考查,因此不能处理负权图
    2. Bellman-Ford每次都直接对所有边进行遍历,因此可适用于负权图和负环图
  • Bellman-Ford的优化:SPFA

实现

int n,m,s;//点数 边数 源点
struct edge{
	int f,t,w;
}e[MAXE];
int dis[MAXV],path[MAXV];
void bellman(){
	fill(begin(dis),end(dis),INF),fill(begin(path),end(path),-1);
    dis[s]=0;
	for(int k=0;k<n-1;k++)//进行V-1次循环
		for(int i=0;i<m;i++)//遍历所有边
			if(dis[e[i].f]!=INF&&e[i].w!=INF&&dis[e[i].t]>dis[e[i].f]+e[i].w){
				dis[e[i].t]=dis[e[i].f]+e[i].w;
				path[e[i].t]=e[i].f;
			}
}

路径输出

void print(int s,int t){
    if(s==t){cout<<s<<' ';return;}
    print(s,path[t]);
    cout<<t<<' ';
}

判断负环

在循环结束后,加入判断是否有边 < u , v > <u,v> <u,v>满足 d i s [ v ] > d i s [ u ] + w dis[v]>dis[u]+w dis[v]>dis[u]+w,若有则表明还可继续松弛,存在负环。

bool check(){
    for(int i=0;i<m;i++)
    	if(dis[e[i].t]>dis[e[i].f]+e[i].w) //若是非连通图,需再加条件dis[e[i].t]!=INF
            return 1;
    return 0;
}

负环还可用SPFA进行判断。

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值