第十九章 Bellman-Ford算法(由SPFA算法逆推BF,独特解读,超级详细)

news2024/11/18 19:36:48

第十九章 Bellman-Ford算法

  • 一、SPFA算法回顾:
  • 二、Bellman-Ford算法
    • 1、算法推导:
    • 1、算法模板:
  • 三、例题:
    • 1、问题:
    • 2、模板:
    • 3、分析:

一、SPFA算法回顾:

我们在第18章中利用dijkstra算法推导出了SPFA算法,如果大家没有看过上一篇文章的话,建议大家先去看作者是如何推导出SPFA算法的,再来看本章节。
传送门:第十八章 SPFA算法以及负环问题

那么今天的Bllman-Ford算法其实就是暴力版本的SPFA

二、Bellman-Ford算法

1、算法推导:

在SPFA算法中,我们利用了队列。另外,我们还使用了一个st数组,这个数组的作用就是标记当前点是否在队里,如果不在队里,我让他入队,如果在队里,我不让它入队。我们通过控制点的入队来避免重复的松弛。那么假设你不明白,那我不管三七二十一,我就让点入队,不管别的,反正最后的结果也只是多重复了几遍,但是结果依旧是正确的。

那么我们在这里思考一下,我们的点最多入队多少次呢?

一个点入队,说明这个点被松弛成功了一次,换句话说我们想知道一个点最多入队多少次,其实就是想知道我们求出一个最短路最多成功松弛多少次。
我们看下面的式子:
在这里插入图片描述

我们知道n个点的最短路,最多含有n-1条边。
假设我们想完成松弛:d[n]<d[n-1]+w,那么我就得先知道d[n-1],想知道d[n-1],就得知道d[n-2]…以此类推。我们发现,我们最多需要松弛n-1次。也就是说,我们的每个点最多入队n-1次。

那么既然这样的话,我们根本没必要去用队列了。直接写一个循环就好了。

1、算法模板:

void Bellman-Ford()
{
	memset(dist, 0x3f, sizeof dist);
	dis[1]=0;
	for(int i=0;i<n-1;i++)
	{
		for(int x=1;<=n;x++)
		{
			for(int y=h[x];y!=-1;y++)
			{
				if(dis[y]>dis[x]+w[y])
				{
					dis[y]=dis[x]+w[y];
				}
			}
		}
	}
}

在这里插入图片描述

以上就是邻接表版本的Bellman-Ford算法。
但是这个代码在形式上,还是有点复杂的。那么我们如何在形式上进行简化呢?我们看下面这个图。
在这里插入图片描述

将最里面的两层循环放在一起看的话,我们发现其实就是访问了每一条边。因此,我们创建一个结构体数组,这个数组存储所有的边。

const int N = 510, M = 10010;
int n, m;
int dist[N];

struct Edge
{
    int a, b, c;
}edges[M];

void bellman_ford()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    for (int i = 0; i < n-1; i ++ )
    {
        for (int j = 0; j < m; j ++ )
        {
            auto e = edges[j];
            dist[e.b] = min(dist[e.b], dist[e.a] + e.c);
        }
    }
}


在这里插入图片描述
我们发现,在最坏情况下,我们循环n-1次,也能找到边数为n-1的最短路(如果存在这样的最短路。)。那么我们延申一下,如果我们循环1次,那么在最坏情况下,我们也能得到边数为1的最短路。

所以,最外层的循环中,我们循环k次的含义就是,我们在最坏情况下也能找到边数为k-1的最短路。

因此,我们看下面这道题:

三、例题:

1、问题:

在这里插入图片描述
当遇到这种有边数限制的最短路问题的时候,我们要想到使用我们的BF算法。

那么我们将该算法的最外层循环设置为k次,那么我们就能保证,即使在最坏的情况下,我们也能找到所有边数小于等于k的最短路
但是,我们也能找到部分大于等于k的最短路:
为什么呢?
我们看一下极端情况:
在这里插入图片描述

假设我们松弛边的顺序为:从右到左遍历。那么我在第一次循环中就能找到边数为n-1的最短路。
那么在最坏情况下:我们从左到右遍历,那么我在第一次循环中只能找到边数为1的最短路。

那么在这道题中,我们很明显要避免掉边数大于k的最短路。

那么怎么办呢?

我们还是以刚才的例子为例:

在最好的情况下,我们之所以能实现连锁反应,是因为我们的上一次成功了。但是如果我们不上一次的结果,那么它就不会成功。

因此,我们松弛本次的时候,只要使用上上次的松弛结果即可。

所以,我们需要加上一个备份的变量。

2、模板:

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510, M = 10010;
struct Edge
{
    int a, b, c;
}edges[M];
int n, m, k;
int dist[N];
int last[N];
void bellman_ford()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    for (int i = 0; i < k; i ++ )
    {
        memcpy(last, dist, sizeof dist);
        for (int j = 0; j < m; j ++ )
        {
            auto e = edges[j];
            dist[e.b] = min(dist[e.b], last[e.a] + e.c);
        }
    }
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edges[i] = {a, b, c};
    }
    bellman_ford();
    if (dist[n] > 0x3f3f3f3f / 2) puts("impossible");
    else printf("%d\n", dist[n]);
    return 0;
}

3、分析:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81154.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【多数据源动态切换】Spring Boot中实现多数据源动态切换效果(1):通过继承AbstractRoutingDataSource类实现

在Spring Boot中&#xff0c;可以通过多种方式实现多数据源的动态切换效果&#xff0c;本篇介绍第一种实现方案。 一 AbstractRoutingDataSource Spring Boot提供了org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource 这个类&#xff0c;其中#determineC…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java校园花卉销售系统ef5ox(1)

做毕业设计一定要选好题目。毕设想简单&#xff0c;其实很简单。这里给几点建议&#xff1a; 1&#xff1a;首先&#xff0c;学会收集整理&#xff0c;年年专业都一样&#xff0c;岁岁毕业人不同。很多人在做毕业设计的时候&#xff0c;都犯了一个错误&#xff0c;那就是不借鉴…

redis之作为分布式锁使用

写在前面 本文一起看下redis作为分布式锁使用的相关内容。 1&#xff1a;怎么算是锁或没锁 锁和没锁本身其实就是用一个变量的值来表示&#xff0c;比如变量lock&#xff0c;当值为1时代表处于上锁状态&#xff0c;当值为0时表示没有锁&#xff0c;那么多线程想要获取锁的话…

【网络工程】8、实操-万达酒店综合项目(二)

接上篇《7、实操-万达酒店综合项目&#xff08;一&#xff09;》 之前我们讲解了酒店网络项目的整体需求文档&#xff0c;包括项目背景、总体架构设计以及网络功能域划分、配置标准、路由规划等。本篇我们就来按照项目要求进行模拟拓扑的构建实操。 一、总体架构效果 按照之前…

力扣 1827. 最少操作使数组递增

题目 给你一个整数数组 nums &#xff08;下标从 0 开始&#xff09;。每一次操作中&#xff0c;你可以选择数组中一个元素&#xff0c;并将它增加 1 。 比方说&#xff0c;如果 nums [1,2,3] &#xff0c;你可以选择增加 nums[1] 得到 nums [1,3,3] 。 请你返回使 nums 严…

2.10.0 以太网 传统STP生成树简介、STP工作方式简单介绍

2.10.0 以太网 传统STP生成树&#xff08;简介、工作方式&#xff09; 作用&#xff1a; STP&#xff08;Spanning Tree Prortoco&#xff09;生成树协议&#xff0c;它的出现解决了交换机网络环路的问题。 交换机网络中收到BUM帧的时候&#xff0c;将会进行泛洪的操作&…

HCIA 以太网的帧

一、前言 网络经常会遇到一些词汇&#xff0c;比如包、报文、帧&#xff0c;其概念如下&#xff1a; 1&#xff09;帧&#xff08;frame&#xff09;&#xff1a;数据链路层的协议数据单元&#xff0c;它包括三部分&#xff1a;帧头、数据部分、帧尾。其中&#xff0c;帧头和…

vector容器模拟实现(上)

1.1:模板设置 因为不能与库已经有的vector冲突&#xff0c;首先定义命名空间namespace my 使用类模板。 1.2:成员变量 vector有size&#xff0c;capacity&#xff0c;同时也要进行扩容操作和缩容&#xff08;shrink to fit&#xff09;操作&#xff0c;所以需要3个迭代器。 p…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java杨柳农贸市场摊位管理系统qr3ri

大四计算机专业的同学们即将面临大学4年的最后一次考验--毕业设计。通过完成毕业设计来对过去4年的大学学习生活做一个总结&#xff0c;也是检验我们学习成果的一种方式&#xff0c;毕业设计作品也是我们将来面试找工作的一个敲门砖。 选题前先看看自己掌握哪些技术点、擅长哪…

mysql首次安装error 1045 28000解决

mysql首次安装error 1045 28000解决 首先找到了这个教程&#xff0c;按其操作一步一步来&#xff0c;发现到登录输入密码这一步&#xff0c;怎么样都报错 2021MySql-8.0.26安装详细教程&#xff08;保姆级&#xff09; 然后按照这篇操作&#xff0c;但还是不行 MySQL安装1045错…

[附源码]Python计算机毕业设计Djangoospringboot作业管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

通过窗口看世界之 界面制作如此简单-带你制作旅游观光系统界面-----效果图展示

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 玩归玩闹归闹&#xff0c;别拿java开玩笑 ⭐旅游管理系统部分效果图展示⭐ 文章目录⭐旅游管理系统部分效果图…

持久化的配置都不知道,也敢说精通Redis?

前言 所谓持久化可以简单理解为将内存中的数据保存到硬盘上存储的过程。持久化之后的数据在系统重启或者宕机之后依然可以进行访问&#xff0c;保证了数据的安全性。一键获取最先java文档。 Redis有两种持久化方案&#xff0c;一种是快照方式&#xff08;SNAPSHOTTING&#xff…

前端 | 前端设计设计及代码收集

全部来源于Github,侵权删&#xff01; 1.Maxime Euzire 2.Shubham Singh | Resume 3.Natasha Theodora Petrus 4.Ana Mara Martnez Gmez 5.bagussona.github.io 6.leodevbro.github.io 7.yuanlinping.github.io 8.Dr.Q 9.sureshmurali.github.io 10.Chandrika Deb | Software…

常见的接口测试面试题

1、按你的理解&#xff0c;软件接口是什么&#xff1f; 答&#xff1a; 就是指程序中具体负责在不同模块之间传输或接受数据的并做处理的类或者函数。 2、HTTP和HTTPS协议区别&#xff1f; 答&#xff1a; https协议需要到CA&#xff08;Certificate Authority&#xff0c;证…

[附源码]JAVA毕业设计医疗器械销售电子商城(系统+LW)

[附源码]JAVA毕业设计医疗器械销售电子商城&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

Spring:Ioc

目录 一、Spring的两大核心机制 1、IOC/ DI:控制反转和依赖注入 2、AOP:面向切面编程 二、IOC/ DI:控制反转 / 依赖注入&#xff1a; 1、bean的基础配置&#xff1a; 2、bean的实例化 3、配置bean 4、依赖注入方式 三、注解开发定义bean 注解依赖注入 Spring设计理念 …

Spring推断构造方法源码深度解析

文章目录前言思考目标一、bean的实例化入口-createBeanInstance1、源码逻辑思路**核心点&#xff0c;主要做了几件事情**2、instantiateBean-默认无参实例化3、instantiate-实例化4、instantiateClass-实例化类二、获取构造函数候选数组-determineConstructorsFromBeanPostProc…

这十套练习,教你如何用Pandas做数据分析(04)

练习4-Apply函数 探索1960 - 2014 美国犯罪数据 步骤1 导入必要的库 运行以下代码 import numpy as np import pandas as pd 步骤2 从以下地址导入数据集 运行以下代码 path4 ‘…/input/pandas_exercise/pandas_exercise/exercise_data/US_Crime_Rates_1960_2014.csv’…

微信小程序|入门进阶

接下来点击新建项目就可以在主界面中预览到我们的豆瓣电影示例了 小程序开发初体验 Hello world 希望是一个从零到一的转换过程~ 创建项目 接下来创建一个新的项目,理解小程序项目的基本结构和一些基础语法。 官方的开发工具为此准备了一个QuickStart项目。在创建过程中,…