存在负权边的单源最短路径的原理和C++实现

负权图
 


此图用朴素迪氏或堆优化迪氏都会出错,floyd可以处理。

负环图


 
但floyd无法处理负权环,最短距离是无穷小。在环上不断循环。

经过k条边的最短距离(可能有负权变)

贝尔曼福特算法(bellman_ford)就是解决此问题的。

原理

循环k次,循环第i次时,m_vDis表示各点最多经过i-1条边的最短距离;vDis表示各点最多经过i条边的最短距离。

核心代码

template<const int INF=1000*1000*1000>
class CBellMan
{
public:
    CBellMan(int n, const vector<vector<int>>& edges,int s , int k )
    {
        m_vDis.assign(n, INF);
        m_vDis[s] = 0;
        for (int i = 1; i <= k; i++)
        {
            vector<int> curDis = m_vDis;
            for (const auto& v : edges)
            {
                if (INF == m_vDis[v[0]])
                {
                    continue;
                }
                curDis[v[1]] = min(curDis[v[1]], m_vDis[v[0]] + v[2]);
            }
            m_vDis.swap(curDis);
        }
    }
    vector<int> m_vDis;
};

测试样例

#include <vector>
#include<assert.h>
using namespace std;


int main()
{
    const int INF = 1000 * 1000 * 1000;
    vector<vector<int>> edges = { {0,1,1},{1,2,2},{2,3,3},{3,0,-7} };
    vector<vector<int>> results = { {0,INF,INF,INF},{0,1,INF,INF},{0,1,3,INF},{0,1,3,6},{-1,1,3,6},{-1,0,3,6},{-1,0,2,6},{-1,0,2,5},{-2,0,2,5} };
    for (int i = 0; i < results.size(); i++)
    {
        CBellMan<> bm(4, edges, 0, i);
        for (int j = 0; j < 4; j++)
        {
            assert(bm.m_vDis[j] == results[i][j]);
        }
    }
}


最短路径

最短路径就是经过“点数-1”条边的最短路径。如果没环,这些边可以到达任意点。如果有正权环和0权环,则拿掉这个环。如果负权环,则最小距离是无穷小。下面来检测负权环。循环“点数-1”后,再循环一次,如果有点的最短距离变小,则一定有负权环;没负权环,不会变短。如果有负权环,则再循环一次,一定有点(任意负权环的负权边的终点)距离变短。假定此点是e,拿掉负权环上所有的边后,源点到e的最短路径为Path。不拿掉负权环,则e的最短路径为:Path+此负权环。

核心代码

template<const int INF=1000*1000*1000>
class CBellMan
{
public:
    CBellMan(int n, const vector<vector<int>>& edges,int s , int k )
    {
        m_vDis.assign(n, INF);
        m_vDis[s] = 0;
        for (int i = 1; i <= k; i++)
        {
            vector<int> curDis = m_vDis;
            Do(edges, curDis);
            m_vDis.swap(curDis);
        }
    }
    bool Check(const vector<vector<int>>& edges)
    {
        vector<int> curDis = m_vDis;
        Do(edges, curDis);
        for (int i = 0; i < curDis.size(); i++)
        {
            if (m_vDis[i] != curDis[i])
            {
                return true;
            }
        }
        return false;
    }
    void Do(const std::vector<std::vector<int>>& edges, std::vector<int>& curDis)
    {
        for (const auto& v : edges)
        {
            if (INF == m_vDis[v[0]])
            {
                continue;
            }
            curDis[v[1]] = min(curDis[v[1]], m_vDis[v[0]] + v[2]);
        }
    }
    vector<int> m_vDis;
};


测试样例

#include <vector>
#include<assert.h>
#include "BellMan.h"
using namespace std;


void Test1()
{
    const int INF = 1000 * 1000 * 1000;
    vector<vector<int>> edges = { { 0,1,1 },{ 1,2,2 },{ 2,3,3 },{ 3,0,-7 } };
    vector<vector<int>> results = { { 0,INF,INF,INF },{ 0,1,INF,INF },{ 0,1,3,INF },{ 0,1,3,6 },{ -1,1,3,6 },{ -1,0,3,6 },{ -1,0,2,6 },{ -1,0,2,5 },{ -2,0,2,5 } };
    for (int i = 0; i < results.size(); i++)
    {
        CBellMan<> bm(4, edges, 0, i);
        for (int j = 0; j < 4; j++)
        {
            assert(bm.m_vDis[j] == results[i][j]);
        }
    }
}

void Test2()
{
    const int INF = 1000 * 1000 * 1000;
    vector<vector<int>> edges = { { 0,1,1 },{ 1,2,2 },{ 2,3,3 },{ 3,0,-7 } };
    vector<int> results = { false,false,true };
    for (int i = 0; i < 3; i++)
    {
        edges[3][2] = -5 - i;
        CBellMan<> bm(4, edges, 0, 3);
        assert(results[i] == bm.Check(edges));
    }
}
int main()
{
    Test1();
    Test2();
}
 


其它

测试环境

win7 VS2019 C++17

相关下载

源码及测试用例
https://download.csdn.net/download/he_zhidan/88393784
doc版文档,排版好
https://download.csdn.net/download/he_zhidan/88348653

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(详解)Linux常见基本指令(1)

目录 目录&#xff1a; 1:有关路径文件下的操作(查看&#xff0c;进入) 1.1 ls 1.2 pwd 1.3 cd 2:创建文件或目录 2.1 touch 2.2 mkdir 3:删除文件或目录 3.1 rm与rmdir 4:复制剪切文件 4.1 cp 4.2 mv 1:有关路径的操作 1 ls 指令 语法&#xff1a;ls [选项] [目录或文…

DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 在数字时代&#xff0c;数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒&#xff08;以下简称DevicData病毒&#xff09;是这场战斗中的新敌人&#xff0c;它能够以毁灭性的方式加密您的数据&#xff0c;迫使您在数据和时间之间做出艰难的选择…

XC5013 马达驱动和充电集成一体的控制芯片 一档输出芯片

XC5013 是一款应用于马达驱动或 LED 驱动的控制芯片&#xff0c;集成了锂电池充电管理系统&#xff0c;设定一档高电平输 出&#xff0c;并带有对不同状态的 LED 指示功能。 XC5013 集成了涓流充电、恒流充电和恒压充电全过程的充电方式&#xff0c;浮充电压精度在全温度范…

网课搜题 小猿题库多接口微信小程序源码 自带流量主

多接口小猿题库等综合网课搜题微信小程序源码带流量主&#xff0c;网课搜题小程序, 可以开通流量主赚钱 搭建教程1, 微信公众平台注册自己的小程序2, 下载微信开发者工具和小程序的源码3, 上传代码到自己的小程序 源码下载&#xff1a;https://download.csdn.net/download/m0_…

[GXYCTF2019]禁止套娃 无回显 RCE 过滤__FILE__ dirname等

扫除git 通过githack 获取index.php <?php include "flag.php"; echo "flag在哪里呢&#xff1f;<br>"; if(isset($_GET[exp])){if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\(…

[极客大挑战 2019]FinalSQL - 异或盲注

1、这题的关键是找注入点&#xff0c;如果选择用户名、密码作为输入点就麻烦了 2、注入点&#xff1a;按钮&#xff0c;点击就传id&#xff1b;当id1时&#xff0c;提示Click others   可以利用id的特性&#xff0c;构造异或匹配   payload: f"1^(ord(substr((select…

【C语言经典100例题-70】求一个字符串的长度(指针)

代码 使用指针来遍历字符串&#xff0c;直到遇到字符串结尾的空字符\0为止&#xff0c;统计字符数量即为字符串长度。 #include<stdio.h> #define n 20 int getlength(char *a) {int len 0;while(*a!\0){len;a;}return len; } int main() {char *arr[n] { 0 };int l…

windows server 2012 服务器打开系统远程功能

服务器上开启远程功能 进入服务器&#xff0c;选择“添加角色和功能” 需要选择安装的服务器类型&#xff0c;如图所示 然后在服务器池中选择你需要使用的服务器。 选择完成后&#xff0c;在图示列表下勾选“远程桌面服务” 再选择需要安装的功能和角色服务。 选择完成确认内容…

JUC第十五讲:JUC集合-ConcurrentHashMap详解(面试的重点)

JUC第十五讲&#xff1a;JUC集合-ConcurrentHashMap详解 本文是JUC第十五讲&#xff1a;JUC集合-ConcurrentHashMap详解。JDK1.7之前的ConcurrentHashMap使用分段锁机制实现&#xff0c;JDK1.8则使用数组链表红黑树数据结构和CAS原子操作实现ConcurrentHashMap&#xff1b;本文…

AUTOSAR RTE介绍(更新版230925)

RTE是什么 AUTOSAR RTE(Run Time Environment)实现了AUTOSAR系统中的虚拟功能总线(VFB),提供了SWC(Software Component)之间的访问接口和SWC对于BSW资源的访问接口。RTE为SWC中的Runnable提供与其他SWC或者BSW模块通信的接口,RTE将Runnable映射到OS Task中,并且管理Runna…

2023(2024届)计算机保研经验分享,圆梦山东大学

前言&#xff1a; Hello大家好&#xff0c;我是Dream&#xff0c;好久不见啦&#xff01;在这不见的半年多时间里我一直在全身心的投入保研之中&#xff0c;在写下这份面经时&#xff0c;真的是感慨颇多&#xff0c;思绪万千。站在这个时间点上&#xff0c;回首过去的几个月&am…

基于SpringBoot的车辆管理系统

目录 前言 一、技术栈 二、系统功能介绍 员工信息管理 证件信息管理 车辆信息管理 事故登记管理 事故登记 保养登记 违章登记 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…

华为云云耀云服务器L实例评测|部署个人音乐流媒体服务器 navidrome

华为云云耀云服务器L实例评测&#xff5c;部署个人音乐流媒体服务器 navidrome 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品规格1.3 产品优势1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 navidrome3.1 navidrome 介绍3.…

redis的持久化消息队列

Redis Stream Redis Stream 是 Redis 5.0 版本新增加的数据结构。 Redis Stream 主要用于消息队列&#xff08;MQ&#xff0c;Message Queue&#xff09;&#xff0c;Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能&#xff0c;但它有个缺点就是消息无法…

C++设计模式-生成器(Builder)

目录 C设计模式-生成器&#xff08;Builder&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-生成器&#xff08;Builder&#xff09; 一、意图 将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 二、…

三分钟学习一个python小知识8-----------我的对python中pandas的理解--补充,

文章目录 一、利用pandas读入excel表&#xff0c;包括csv,xlsx等格式二、利用pandas读取没有表头的表格1.引入库 三、利用pandas读取有表头的表格四、利用pandas读取表格中的第一列五、利用pandas导出为excel数据总结 一、利用pandas读入excel表&#xff0c;包括csv,xlsx等格式…

Django 模型层的操作(Django-05 )

一 模型层的解读 Django中内嵌了ORM框架&#xff0c;不需要直接编写SQL语句进行数据库操作&#xff0c;而是通过定义模型类&#xff0c;操作模型类来完成对数据库中表的增删改查和创建等操作。 O 是object&#xff0c;也就类对象的意思。R 是relation&#xff0c;翻译成中文是…

保险业SAP转型:奠定坚实的基础

保险业面临着许多新的挑战&#xff1a;从新的市场参与者到人工智能和物联网。如何在这种快节奏的现实中满足客户的需求&#xff0c;降低成本&#xff0c;加速增长&#xff1f;首先&#xff0c;让我们考虑一下数字化转型成功是什么样子的&#xff0c;以及如何实现它。在这篇文章…

基于微信小程序的付费自习室

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 需求分析3.1用户需求分析3.1.1 学生用户3.1.3 管理员用户 4 数据库设计4.4.1 E…

《计算机视觉中的多视图几何》笔记(13)

13 Scene planes and homographies 本章主要讲述两个摄像机和一个世界平面之间的射影几何关系。 我们假设空间有一平面 π \pi π&#xff0c;平面上的一点为 x π x_{\pi} xπ​。 x π x_{\pi} xπ​分别在两幅图像 P , P ′ P, P P,P′上形成了 x , x ′ x, x x,x′。 那…