IGraph使用实例——贝尔曼-福特算法(求解单源最短路径)

1 概述

本文中求解最短路径使用的方法是igraph中基于贝尔曼-福特算法(Bellman-Ford算法)。Bellman-Ford算法是一种用于在加权图中找到从单个源点到所有其他顶点的最短路径的算法。这个算法可以处理包含负权重边的图,但不能处理有负权重循环的图,因为负权重循环会导致最短路径不存在。

2 运行环境

操作系统:win10 64位

编程语言:C/C++

编译平台:vs2019  x64 debug | release

igraph版本: 0.10.12

3 示例代码

 在igraph中igraph_distances_bellman_ford 函数被用来执行Bellman-Ford算法。以下是函数的说明:

igraph_distances_bellman_ford(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT);

函数参数说明:

  • &g 是指向图的指针。
  • &res 是指向矩阵的指针,该矩阵将存储从每个顶点到其他所有顶点的最短路径长度。
  • igraph_vss_all() 表示源点和目标点都是图中的所有顶点。
  • &weights 是指向存储边权重的向量的指针。
  • IGRAPH_OUT 表示算法将基于图的出边来计算最短路径。

Bellman-Ford算法的工作原理是通过迭代松弛边来逐步更新从源点到其他顶点的最短路径估计。这个过程重复进行,直到没有更多的边可以松弛,或者检测到负权重循环为止。在代码中,对于包含负权重的图,算法将正常执行并给出最短路径;而对于包含负权重循环的图,算法将返回错误代码 IGRAPH_ENEGLOOP

这段代码是一个C语言程序,它使用了IGraph库来计算图中的最短路径。程序分为三个部分,分别处理了三种不同情况的图:只有正权重的图、含有负权重的图以及含有负权重循环的图。下面是对代码的逐行解释。

// 包含IGraph库的头文件
#include <igraph.h>

int main(void) {
    // 声明一个图变量g
    igraph_t g;
    // 声明一个向量weights,用于存储边的权重
    igraph_vector_t weights;
    // 定义一组权重数据,用于正权重图
    igraph_real_t weights_data_0[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    // 定义另一组权重数据,用于含有负权重的图
    igraph_real_t weights_data_1[] = { 6, 7, 8, -4, -2, -3, 9, 2, 7 };
    // 定义第三组权重数据,用于含有负权重循环的图
    igraph_real_t weights_data_2[] = { 6, 7, 2, -4, -2, -3, 9, 2, 7 };
    igraph_matrix_t res;

    /* Graph with only positive weights */
    // 创建一个有10个顶点的有向图,添加边和对应的权重,-1表示边的列表结
    igraph_small(&g, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,         3, 2, 3, 6,
                 4, 5, 4, 7,         5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,         8, 9,
                 5, 2,
                 2, 1,
                 -1);
    // 创建一个视图,将weights_data_0数组作为weights向量的底层数据
    igraph_vector_view(&weights, weights_data_0,
                       sizeof(weights_data_0) / sizeof(weights_data_0[0]));
    // 计算数组元素个数
    igraph_matrix_init(&res, 0, 0);
    // 计算从所有顶点到所有其他顶点的最短路径(使用Bellman-Ford算法,权重向量为weights,按出边)
    igraph_distances_bellman_ford(&g, &res, igraph_vss_all(), igraph_vss_all(),
                                  &weights, IGRAPH_OUT);
    // 打印矩阵res中的结果
    igraph_matrix_print(&res);
    // 销毁矩阵res
    igraph_matrix_destroy(&res);
    // 销毁图g
    igraph_destroy(&g);

    printf("\n");

    /***************************************/

    /* Graph with negative weights */
    // 创建一个有5个顶点的有向图,并添加边和对应的权重
    igraph_small(&g, 5, IGRAPH_DIRECTED,
                 0, 1, 0, 3, 1, 3, 1, 4, 2, 1, 3, 2, 3, 4, 4, 0, 4, 2, -1);
    // 使用weights_data_1数组作为权重
    igraph_vector_view(&weights, weights_data_1,
                       sizeof(weights_data_1) / sizeof(weights_data_1[0]));
    // 重新初始化矩阵res
    igraph_matrix_init(&res, 0, 0);
    // 计算从所有顶点到所有其他顶点的最短路径
    igraph_distances_bellman_ford(&g, &res, igraph_vss_all(),
                                  igraph_vss_all(), &weights, IGRAPH_OUT);
    // 打印矩阵res中的结果
    igraph_matrix_print(&res);

    /***************************************/

    /* Same graph with negative loop */
    // 设置错误处理函数,忽略错误
    igraph_set_error_handler(igraph_error_handler_ignore);
    // 使用weights_data_2数组作为权重
    igraph_vector_view(&weights, weights_data_2,
                       sizeof(weights_data_2) / sizeof(weights_data_2[0]));
    
    // 尝试计算最短路径,检查是否有负权重循环
    if (igraph_distances_bellman_ford(&g, &res, igraph_vss_all(),
                                      igraph_vss_all(),
                                      &weights, IGRAPH_OUT) != IGRAPH_ENEGLOOP) {
        // 如果没有检测到负权重循环,返回错误代码1
        return 1;
    }
    // 销毁矩阵res
    igraph_matrix_destroy(&res);
    // 销毁图g
    igraph_destroy(&g);

    // 检查是否有未完成的操作
    if (!IGRAPH_FINALLY_STACK_EMPTY) {
        // 如果有,返回错误代码1
        return 1;
    }
    // 正常退出,返回0
    return 0;
}

4 运行结果

根据提供的运行结果,我们可以看到两部分输出:

  1. 第一部分是一个矩阵,它表示的是第一个图中从每个顶点到其他所有顶点的最短路径长度。在这个矩阵中,"Inf" 表示无穷大,即不存在路径或者路径长度为无穷大。矩阵中的数字表示从行顶点到列顶点的最短路径长度。

  2. 第二部分是第二个图的邻接矩阵表示,其中正值表示正权重的边,负值表示负权重的边。

现在,让我们分析第一部分的输出:

这个矩阵显示了从每个顶点到其他顶点的最短路径长度。例如,从顶点0到顶点1的最短路径长度是0(因为它们是同一个顶点),从顶点0到顶点4的最短路径长度是5。如果某个值是"Inf",这意味着从该行的顶点到该列的顶点没有路径。

第二部分的输出是一个邻接矩阵,它表示第二个图的边和权重:

在这个邻接矩阵中,矩阵的行和列代表图的顶点,矩阵中的值代表顶点之间的边的权重。例如,从顶点0到顶点2的边的权重是4,从顶点1到顶点3的边的权重是2。负值表示边的权重是负数。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTFHUB-技能树-web-web前置技能-HTTP协议全

目录 1.请求方式 2.302跳转 3.Cookie 4.基础认证 5.响应包源码 1.请求方式 curl -v -X http://challenge-3022c877a8dcedeb.sandbox.ctfhub.com:10800/index.php 2.302跳转 参考链接&#xff1a;http://t.csdnimg.cn/aqdNG 301——永久性重定向。该状态码表示请求的资源已…

Springboot vue elementui 前后端分离 事故灾害案例管理系统

源码链接 系统演示:https://pan.baidu.com/s/1hZQ25cpI-B4keFsZdlzimg?pwdgw48

构造,CF862C. Mahmoud and Ehab and the xor

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 862C - Codeforces 二、解题报告 1、思路分析 非常松的一道构造题目 我们只需让最终的异或和为x即可 下面给出个人一种构造方式&#xff1a; 先选1~N-3&#xff0c;然后令o (1 << 17) …

树莓集团领航:园区运营新标杆

在当今经济飞速发展的时代&#xff0c;产业园区作为推动地方经济增长、优化产业布局的重要平台&#xff0c;其运营和管理水平至关重要。树莓集团&#xff0c;作为园区运营的政企典范&#xff0c;凭借其专业的运营能力和卓越的服务品质&#xff0c;赢得了业界的广泛赞誉。 树莓…

大模型 vs 数据资产,谁才是真正的BOSS?

大数据产业创新服务媒体 ——聚焦数据 改变商业 在数字化时代的浪潮中&#xff0c;数据资产管理已成为企业战略中不可或缺的一环。随着数据量的激增&#xff0c;如何有效管理、利用这些数据&#xff0c;提炼其价值&#xff0c;成为了摆在每个组织面前的重大挑战。在这个背景下…

dataframe元组和字典操作

这是一个测试文件&#xff0c;今天发现一些有意思的语法&#xff0c; 首先字典是可以加入元组的 AA {"a":2,"b":23,"c":(1,2,3)} print(AA)结果如下 example1 import pandas as pd data pd.DataFrame(data {"a":(-1,-2,-3),&quo…

大数据—元数据管理

在大数据环境中&#xff0c;元数据管理是确保数据资产有效利用和治理的关键组成部分。元数据是描述数据的数据&#xff0c;它提供了关于数据集的上下文信息&#xff0c;包括数据的来源、格式、结构、关系、质量、处理历史和使用方式等。有效的元数据管理有助于提高数据的可发现…

HTML+CSS+JS 倒计时动画效果

效果演示 实现了一个倒计时动画效果,包括数字区域和倒计时结束区域。数字区域显示倒计时数字,数字进入时有动画效果,数字离开时也有动画效果。倒计时结束后,数字区域隐藏,倒计时结束区域显示,显示时也有动画效果。用户可以点击重新开始按钮重新开始倒计时。 Code <!D…

上海亚商投顾:创业板指震荡收涨 超70家ST股跌停

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡震荡&#xff0c;创业板指走势稍强&#xff0c;盘中一度涨超1%&#xff0c;黄白二线分化严重。算…

【Spring框架全系列】SpringBoot_3种配置文件_yml语法_多环境开发配置(详细)

文章目录 1.三种配置文件2. yaml语法2.1 yaml语法规则2.2 yaml数组数据2.3 yaml数据读取 3. 多环境开发配置 1.三种配置文件 问题导入 框架常见的配置文件有哪几种形式&#xff1f; 比如&#xff1a; jdbc.properties spring.properties 如果每个技术或者框架都要这么写一个配…

404错误页面源码,简单实用的html错误页面模板

源码描述 小编精心准备一款404错误页面源码&#xff0c;简单实用的html错误页面模板&#xff0c;简单大气的页面布局&#xff0c;可以使用到不同的网站中&#xff0c;相信大家一定会喜欢的 效果预览 源码下载 https://www.qqmu.com/3375.html

Linux 命令 | 运维必学,用户和组管理命令实践集锦

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] 大家好&#xff0c;我是一个正在向全栈工程师(SecDevOps)前进的计算机技术爱好者 作者微信&#xff1a;WeiyiGeeker公众号/星球&#xff1a;全栈工程师修炼指南主页博客: https://weiyigeek.top -…

Samtec技术前沿 | 全新224G互连产品系列现场演示

【摘要/前言】 数据中心、人工智能、机器学习和量子计算等领域的行业进步推动了新兴系统需求的增长。Samtec 224 Gbps PAM4 互连系统经过精心设计&#xff0c;能够满足这些高性能要求&#xff0c;您将在视频中看到这一点。 【Demo演示】 Samtec 系统架构师Ralph Page讲述了可…

使用 Django 创建 App

文章目录 步骤 1&#xff1a;创建 Django 项目步骤 2&#xff1a;创建 App步骤 3&#xff1a;配置 App步骤 4&#xff1a;编写代码步骤 5&#xff1a;运行服务器 在 Django 中&#xff0c;App 是组织代码的基本单元&#xff0c;它可以包含模型、视图、模板等组件&#xff0c;帮…

FreeRTOS【15】事件组使用

1.开发背景 基于以上的章节&#xff0c;了解了 FreeRTOS 多线程间的信号量、队列的使用&#xff0c;已经满足了日常使用场景。其中信号量可以实现线程同步&#xff0c;对标的是裸机的 Flag 标识&#xff0c;但是在裸机中经常使用的不止一个标识&#xff0c;如果用二值信号量去实…

嵌入式Linux内核调试之使用模块参数详解

基本要求 环境: 处理器架构:arm64 内核源码:linux-6.6.29 ubuntu版本:20.04.1 代码阅读工具:vim+ctags+cscope 本文主要介绍内核开发中常用的模块传参手段,通过模块参数传递可以通过用户态来获取内核的一些信息,也可以通过用户态写入一些值来控制内核相关行为。一般内核…

PDF软件PDF Extra Premium + Ultimate 9.30.56026

PDF Extra Premium是一个适用于Windows的程序,它提供了所有功能,***在一个地方处理PDF文件的需要。使用此程序,您可以: 扫描和识别文本。您可以轻松地将纸质文档扫描并数字化为可编辑的PDF文件。您可以使用手机的摄像头扫描任何类型的纸质文档:支票、合同、票据、票据、证…

Gitlab---添加描述模版

0 Preface/Foreword Gitlab是代码托管平台&#xff0c;DevOps。因其免费&#xff0c;被广泛使用。GitLab不但可以管理代码&#xff0c;也可以管理issue&#xff0c;创建milestone等等。针对issue管理&#xff0c;支持描述模版功能&#xff0c;即对于新建的issue&#xff0c;可…

Golang | Leetcode Golang题解之第130题被围绕的区域

题目&#xff1a; 题解&#xff1a; var (dx [4]int{1, -1, 0, 0}dy [4]int{0, 0, 1, -1} ) func solve(board [][]byte) {if len(board) 0 || len(board[0]) 0 {return}n, m : len(board), len(board[0])queue : [][]int{}for i : 0; i < n; i {if board[i][0] O {q…

软件测试、测试模型、测试用例

软件开发的五个模型 瀑布模型&#xff08;Waterfall Model&#xff09; 瀑布模型是所有其他模型的基础框架&#xff0c;瀑布模型的每个阶段都只执行一次&#xff0c;因此是线性顺序进行的开发模式优点&#xff1a;强调开发的阶段性&#xff1b; 强调早期计划及需求调查&#…