Floyd算法——AcWing 343. 排序

目录

Floyd算法

定义

运用情况

注意事项

解题思路

基本步骤

AcWing 343. 排序 

题目描述

运行代码

代码思路

改进思路

Floyd算法

定义

Floyd算法,全称Floyd-Warshall算法,是一种用于解决图中所有顶点对之间的最短路径问题的动态规划算法。它适用于带权有向图,且可以处理负权重边(但不能处理含有负权重循环的图),并能够检测出图中是否存在负权重循环。

运用情况

  1. 计算所有顶点对之间的最短路径:在诸如社交网络分析、交通网络规划、通信网络设计等领域,需要计算任意两点间的最短距离时,Floyd算法是一个很好的选择。
  2. 检测负权重循环:在某些应用场景下,需要确保图中不存在负权重循环,因为这可能表示系统中的某种异常或错误状态。

注意事项

  • 内存消耗:Floyd算法的空间复杂度为O(n^2),其中n是图中顶点的数量。对于大规模图,这可能成为一个问题。
  • 时间复杂度:Floyd算法的时间复杂度为O(n^3),在顶点数量很大的情况下,算法可能会变得非常慢。
  • 负权重循环:如果图中存在负权重循环,Floyd算法会陷入无限循环,因为从一个节点出发,通过该循环可以无限次减少路径长度。在实际应用中,需要先检测并处理这类情况。
  • 算法可以检测负权重循环:如果在算法执行过程中发现某个顶点到自身的最短路径小于0,即D[i][i] < 0,那么图中存在至少一个负权重循环,此时算法无法给出正确的最短路径结果。
  • 对于非常大的图,算法的高时间复杂度和空间复杂度可能成为瓶颈,这时可能需要考虑更高效的算法或者使用更专业的数据结构和优化技术。

解题思路

Floyd算法的核心思想是动态规划,其基本步骤如下:

  1. 初始化:将距离矩阵D设置为图的邻接矩阵,即D[i][j] = weight(i, j);对于i != j,如果(i, j)不连通,则D[i][j] = ∞;D[i][i] = 0。
  2. 动态规划:对于k = 1 到 n,更新D,使得D[i][j] = min(D[i][j], D[i][k] + D[k][j]),即检查是否可以通过中间节点k来缩短i到j的距离。
  3. 结果:最终的D矩阵包含了所有顶点对之间的最短路径长度。如果存在某个D[i][j] < 0且i != j,在更新过程中出现了D[i][i] < 0的情况,说明图中存在负权重循环。

Floyd算法的实现通常使用三重循环,外层循环遍历所有的中间顶点k,内两层循环遍历所有顶点对(i, j),检查是否存在更短路径。

基本步骤

假设我们有一个带权图G,其中包含n个顶点,我们可以用一个二维数组dist[][]来存储每对顶点之间的最短路径长度。初始时,dist[i][j]被设定为图中直接相连的边的权重,如果i和j之间没有直接相连的边,则dist[i][j]被设定为无穷大(表示不可达)。

  1. 初始化:创建一个n×n的矩阵D,其中D[i][j]初始化为图中从i到j的直接边的权重,如果i和j之间没有直接边,则设为无穷大。对角线元素D[i][i] = 0。

  2. 动态规划:对于每个顶点k(作为中间顶点),更新每对顶点i和j之间的最短路径,以k为中间点可能获得更短路径。更新公式为:D[i][j] = min(D[i][j], D[i][k] + D[k][j])。这意味着,如果通过k作为中间顶点,从i到j的路径变得更短了,就更新D[i][j]。

  3. 结果输出:经过n轮迭代后,矩阵D中的每个元素D[i][j]即为从i到j的最短路径长度。

AcWing 343. 排序 

题目描述

343. 排序 - AcWing题库

运行代码

#include <algorithm>
#include <bits/stdc++.h>
#include <iostream>
using namespace std;

#define PII pair<int, int>
#define fi first
#define se second
#define endl '\n'
map<int, int> mp;

const int N = 210, mod = 1e9 + 7;
int T, n, m, k;
int a[N], dist[N][N];
PII ans[N];

void floyd(int x) // 以 x 为中转点,更新其他点。
{
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            dist[i][j] = min(dist[i][j], dist[i][x] + dist[x][j]);
}

bool pd() // 判断是否所有点都已确定
{
    for (int i = 1; i <= n; i++) {
        int cnt = 0;
        for (int j = 1; j <= n; j++)
            if (dist[i][j] != 1e9)
                cnt++; // 当前点能到达的点数
        ans[i] = {cnt, i};
        for (int j = 1; j <= n; j++)
            if (i != j && dist[j][i] != 1e9)
                cnt++; // 能到达当前点的点数
        if (cnt != n)
            return 0;
    }
    sort(ans + 1, ans + n + 1);
    return 1;
}

int main() {
    while (cin >> n >> m && n) {
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (i != j)
                    dist[i][j] = 1e9;

        int flag = 0;
        for (int i = 1; i <= m; i++) {
            char a, t, b;
            cin >> a >> t >> b;
            int x = a - 'A' + 1, y = b - 'A' + 1; // 现在要加一条从 y 到 x 的边

            if (!flag && dist[x][y] != 1e9) // 发现已经从x能到y,出现矛盾
            {
                printf("Inconsistency found after %d relations.\n", i);
                flag = 1;
            }

            dist[y][x] = 1;
            floyd(x), floyd(y); // 分别以 x 和 y 为中转点更新其他点
            if (!flag && pd()) { // 发现所有点都已确定
                printf("Sorted sequence determined after %d relations: ", i);
                for (int i = 1; i <= n; i++)
                    cout << char(ans[i].se + 'A' - 1);
                printf(".\n");
                flag = 1;
            }
        }
        if (!flag)
            printf("Sorted sequence cannot be determined.\n"); // 无法确定
    }

    return 0;
}

代码思路

  1. 初始化: 使用一个dist二维数组初始化为无穷大,表示不等式间默认没有确定的顺序关系。
  2. 读取输入: 从标准输入读取关系,格式为“B > A”,表示B优于A。
  3. 关系处理:
    • 当读取到新的关系时,检查是否有矛盾(即之前已确定的关系与新关系冲突)。
    • 更新dist矩阵,使用Floyd算法更新所有不等式之间的最短路径,这里实际上是更新“优先级”或“排序”的关系。
  4. 检查排序确定性:
    • 检查是否所有不等式之间的关系都已经确定,即每个点都能到达其他所有点,且路径长度不是无穷大。
    • 如果在读取关系的过程中就发现了排序确定,或者读取完所有关系后仍然无法确定排序,输出相应信息。

改进思路

  • 效率提升: 当前的floyd调用在每次添加新关系后立即进行,这可能不是必要的。可以等到所有关系读取完毕后再进行一次Floyd算法,以减少不必要的计算。
  • 简化逻辑: 目前的代码在检测矛盾和确定排序完成的逻辑较为复杂。可以尝试简化逻辑,比如使用更直观的数据结构或算法步骤来检查这些条件。
  • 代码清晰性: 可以增加注释和代码结构的清晰度,使得代码更易于理解和维护。

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

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

相关文章

【Memcached】Memcached的工作原理

目录 ​编辑 第2章&#xff1a;Memcached工作原理 2.1 数据存储与访问 2.2 分布式架构 2.3 数据过期机制 第2章&#xff1a;Memcached工作原理 2.1 数据存储与访问 Memcached是一种键值存储系统&#xff0c;其中数据以键值对的形式存储。键是用于定位数据的唯一标识符&am…

13 IP层协议-网际控制报文协议ICMP

计算机网络资料下载&#xff1a;CSDNhttps://mp.csdn.net/mp_blog/creation/editor/140148186 为了更有效的转发IP数据报和提高交付成果的机会&#xff0c;在网际层使用了网际控制报文协议ICMP。ICMP允许主机或路由器报告差错情况和提供有关异常情况的报告。ICMP不是高层协议数…

【系统架构设计师】十一、系统架构设计(层次架构风格|MVC|面向服务的架构风格|ESB)

目录 五、层次架构风格 5.1 两层C/S架构 5.2 三层C/S架构 5.3 三层B/S架构 5.4 MVC架构 5.5 MVP架构 5.6 MVVM架构 六、面向服务的架构风格 6.1 SOA特征 6.2 Web Service 6.2.1 关键技术 6.2.2 WEB Service 6.3 企业服务总线ESB 相关推荐 历年真题练习 五、层次…

[Linux]添加sudoers

之前我们讲过sudo这个命令,它可以让我们普通用户进行短暂的提权,上回我们讲完了vim 本篇是个短篇,目的就是让我们之后的学习中可以使用sudo命令。 首先我们先登录root用户 ls /etc/sudoer 我们需要改的就是上面的这个文件 vim /etc/sudoers 我们用vim打开 把光标移动到这…

类和对象(中)-- 类的六个默认成员函数

目录 1.构造函数 1.1构造函数的特性 1.2 默认构造函数 1.3补丁 ​2.析构函数 2.1析构函数的特性 2.2构造函数与析构函数的调用顺序 3.拷贝构造函数&#xff08;复制构造函数&#xff09; 3.1拷贝构造函数的特征 4.赋值运算符重载 4.1运算符重载 4.2类内重载运算符 …

ChatGPT 深度解析:技术驱动的智能对话

在当今科技飞速发展的时代&#xff0c;ChatGPT 无疑成为了最耀眼的明星之一。它以其令人惊叹的智能对话能力&#xff0c;引发了全球范围内的广泛关注和热议。 ChatGPT 背后的技术堪称精妙绝伦。它基于深度学习算法&#xff0c;通过对海量数据的学习和分析&#xff0c;从而能够理…

浅谈Git

一&#xff1a;什么是 git git一种开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 下图是 git 的一个工作流程简图 二&#xff1a;什么是 分布/集中式版本控制系统 软件开发过程中&#xff0c;要解决多人协作的问题&#xff0c;需要…

【Linux】常见指令(下)

【Linux】常见指令&#xff08;下&#xff09; 通配符 *man指令cp指令echo指令cat指令&#xff08;简单介绍&#xff09;cp指令 mv指令alias指令which ctrl ccat指令linux下一切皆文件 more指令less指令head指令tail指令管道 通配符 ‘*’ 通配符’ *‘&#xff0c;是可以匹配…

Linux(CentOS7)离线安装Redis6

版本 CentOS-7、redis-6 1、下载redis离线包 下载地址&#xff1a;http://download.redis.io/releases/ 2、选择安装包 redis-6.2.5.tar.gz 3、上传安装包至服务器 cd /usr/local/redis #进入目录&#xff0c;没有redis目录则自行创建 tar -zxvf redis-6.2.5.tar.gz #…

【信息收集】域名信息收集

域名介绍 域名&#xff08;Domain Name&#xff09;&#xff0c;简称域名、网域&#xff0c;是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称&#xff0c;用于在数据传输时标识计算机的电子方位&#xff08;有时也指地理位置&#xff09;。 DNS&#xf…

解决RuntimeError: Couldn‘t load custom C++ ops. This can happen if your PyTorch

问题描述 刚下好yolov8的代码&#xff0c;想测一下能否成果&#xff0c;果然没成功&#xff0c;报错如下 RuntimeError: Couldnt load custom C ops. This can happen if your PyTorch and torchvision versions are incompatible, or if you had errors while compiling tor…

【python】Pandas运行报错分析:SettingWithCopyWarning及其处理

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

通用图形处理器设计GPGPU基础与架构(三)

一、前言 前两篇已经介绍了 GPGPU 的背景 和 GPGPU 的编程模型相关的内容&#xff0c;本文将在 SIMT 计算模型的基础上&#xff0c;介绍 GPGPU 控制核心架构和微体系结构的设计。 二、CPU-GPGPU 异构计算系统 一个由 CPU 和 GPGPU 构成的异构计算平台如下图所示&#xff0c;GP…

《昇思25天学习打卡营第23天|ResNet50迁移学习》

文章目录 ResNet50迁移学习数据准备下载数据集 加载数据集数据集可视化 训练模型构建Resnet50网络固定特征进行训练训练和评估可视化模型预测 总结打卡 ResNet50迁移学习 在实际应用场景中&#xff0c;由于训练数据集不足&#xff0c;所以很少有人会从头开始训练整个网络。普遍…

摸鱼大数据——Kafka——kafka tools工具使用

可以在可视化的工具通过点击来操作kafka完成主题的创建&#xff0c;分区等操作 注意: 安装完后桌面不会有快捷方式,需要去电脑上搜索,或者去自己选的安装位置找到发送快捷方式到桌面! 连接配置 创建主题 删除主题 主题下的数据查看 数据显示问题说明 修改工具的数据显示类型 发…

Laravel :如何将Excel文件导入数据库

文章目录 一、前提二、使用2.1、新建一个导入文件2.2、新建一个控制器和方法,调用导入文件2.3、 新建一个页面&#xff0c;支持文件上传 一、前提 想要将excel内容入库&#xff0c;laravel有扩展可以使用,常用的扩展是maatwebsite/excel&#xff0c;安装步骤参考上一篇&#x…

校园工会体育报名小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;赛事公告管理&#xff0c;球员管理&#xff0c;球队信息管理&#xff0c;比赛信息&#xff0c;比赛报名管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;比赛信息&#xff0c;比赛报名&#…

7月考研数学的保底进度,警惕三个误区!

误区1. 不恰当的课程选择和学习计划 尤其25张宇36讲大改版&#xff0c;一些同学感到焦虑&#xff0c;担心自己的课程选择不适合自己。 或者担心学习计划不够高效&#xff0c;影响最终的成绩。 课程选择&#xff0c;看3方面&#xff1a; 1. 覆盖是否全面&#xff1f; 2. 是否…

element-ui dialog 嵌套

dialog 内部嵌套 dialog&#xff0c;内层的 dialog 层级显示会遮罩在内容的 dialog 内容区域之上&#xff0c;内层 dialog 添加 append-to-body 属性即可&#xff0c;如官方文档&#xff1a;

网安小贴士(11)VPN类型

前言 VPN&#xff08;Virtual Private Network&#xff0c;虚拟专用网络&#xff09;类型多样&#xff0c;主要根据其使用的协议、应用场景以及实现方式等因素进行分类。以下是对VPN类型的详细概述&#xff1a; 一、按协议分类 根据使用的隧道协议&#xff0c;VPN可以分为以下几…