Floyd算法——AcWing 343. 排序

news2024/9/24 5:31:30

目录

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算法,以减少不必要的计算。
  • 简化逻辑: 目前的代码在检测矛盾和确定排序完成的逻辑较为复杂。可以尝试简化逻辑,比如使用更直观的数据结构或算法步骤来检查这些条件。
  • 代码清晰性: 可以增加注释和代码结构的清晰度,使得代码更易于理解和维护。

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

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

相关文章

配置Java开发环境

Java是一种广泛使用的编程语言&#xff0c;特别是在企业应用和安卓开发中。本文将详细介绍如何在您的计算机上配置Java开发环境&#xff0c;包括安装JDK、配置环境变量以及选择和设置IDE。 一、安装Java Development Kit (JDK) JDK&#xff08;Java Development Kit&#xff0…

用JavaScript将 NCR(Numeric Character Reference)标记转换为对应字符的方法

0 &#xff0c 、&#11111……是什么鬼&#xff1f; 最近&#xff0c;要将一些网页内容复制到<textarea>文本框中作进一步处理&#xff0c;发现有些网页内容中包含&#xff0c或之类的标记&#xff0c;会被原样复制到<textarea>文本框中。 如果将这些网页内容直…

AI Agent 的发展现状、行业结构与趋势分析

Agent 来自一种哲学概念&#xff0c;是个很古老的哲学术语&#xff0c;从哲学意义上讲&#xff0c;“代理”的概念涉及实体的自主性&#xff0c;具有行使意志、做出选择和采取行动的能力&#xff0c;而不是被动地对外部刺激做出反应。后来人们将这一概念引入计算机科学领域&…

285个地级市-胡焕庸线数据

全国285个地级市-胡焕庸线数据.zip资源-CSDN文库 胡焕庸线&#xff1a;中国人口与生态的分界线 胡焕庸线&#xff0c;一条在中国地理学界具有划时代意义的分界线&#xff0c;由著名地理学家胡焕庸于1935年提出。这条线从黑龙江省的瑷珲&#xff08;现黑河市&#xff09;延伸至…

又上热搜!曝iPhone 16将支持40W快充

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 7月9日晚&#xff0c;微博话题“iPhone16系列或将支持40W快充”上了热搜榜&#xff0c;这已经是iPhone 16系列第N次上热搜了。 据爆料&#xff0c;iPhone 16系列充电功率将提升至40W&#xff0c;并且…

Deepspeed : AttributeError: ‘DummyOptim‘ object has no attribute ‘step‘

题意&#xff1a;尝试在一个名为 DummyOptim 的对象上调用 .step() 方法&#xff0c;但是这个对象并没有定义这个方法 问题背景&#xff1a; I want to use deepspeed for training LLMs along with Huggingface Trainer. But when I use deepspeed along with trainer I get …

书生大模型实战营(暑假场)-入门岛-第二关

目录 关卡任务 任务一 任务二 总结 关卡任务 任务一&#xff1a; 请实现一个wordcount函数&#xff0c;统计英文字符串中每个单词出现的次数。返回一个字典&#xff0c;key为单词&#xff0c;value为对应单词出现的次数。 这个算是比较简单的了&#xff0c;代码如下所示 …

C基础day8

一、思维导图 二、课后习题 #include<myhead.h> #define Max_Stu 100 //函数声明 //学生信息录入函数 void Enter_stu(int *Num_Stu,char Stu_name[][50],int Stu_score[]); //查看学生信息 void Print_stu(int Num_Stu,char Stu_name[][50],int Stu_score[]); //求出成绩…

Rust vs Go: 特点与应用场景分析

目录 介绍Rust的特点Go的特点Rust的应用场景Go的应用场景总结 介绍 Rust和Go&#xff08;Golang&#xff09;是现代编程语言中两个非常流行的选择。凭借各自的独特优势和广泛的应用场景&#xff0c;吸引了大量开发者的关注。本文将详细介绍Rust和Go的特点&#xff0c;并探讨它…

OpenCV 寻找棋盘格角点及绘制

目录 一、概念 二、代码 2.1实现步骤 2.2完整代码 三、实现效果 一、概念 寻找棋盘格角点&#xff08;Checkerboard Corners&#xff09;是计算机视觉中相机标定&#xff08;Camera Calibration&#xff09;过程的重要步骤。 OpenCV 提供了函数 cv2.findChessboardCorners…

C++ 宏和内联、范围for、nullptr

C 宏函数和内联函数、范围for、nullptr 宏函数和内联函数 ​ 函数重载中提到过&#xff0c;一个程序编译需要经过四个阶段&#xff0c;第一个阶段预处理中有一个操作是宏替换。由于是替换&#xff0c;所以宏不建立栈帧&#xff0c;且没有数据类型的限制&#xff0c;能够提高我…

ESP-12F 异常烧录一例

自己打了一块esp8266 &#xff0c;esp 12f的模组&#xff0c;品牌是B&T ,某公司的子品牌吧。 玩单片机这么久&#xff0c;终于玩到了自己打nodemcu这种版了。 遇到一些问题汇总如下供参考&#xff1a; 1&#xff0c;模组IO2自带了led,后来只能拆了我画的线路&#xff0c;…

Canvas:实现在线画板操作

想象一下&#xff0c;用几行代码就能创造出如此逼真的图像和动画&#xff0c;仿佛将艺术与科技完美融合&#xff0c;前端开发的Canvas技术正是这个数字化时代中最具魔力的一环&#xff0c;它不仅仅是网页的一部分&#xff0c;更是一个无限创意的画布&#xff0c;一个让你的想象…

前后端如何实现非对称加解密-使用RSA为例讲解!

写在最前面&#xff0c;RSA是一种非对称加密算法&#xff0c;使用不同的公钥和私钥进行加密和解密。 下面是使用RSA进行加密和解密的代码示例&#xff1a; 前端&#xff1a;使用CryptoJS进行RSA加密 在前端JavaScript中&#xff0c;使用jsencrypt库来进行RSA加密&#xff1a…

04OLED简介和调试方法

OLED简介和调试方法 调试方式串口调试显示屏调试其他调试方法总结&#xff1a; OLED简介硬件电路OLED驱动函数 keil调试模式进入方法keil调试界面窗口简单功能说明更加强大的功能 调试方式 电脑想看什么变量可以直接打印到屏幕&#xff0c;但是单片机很多时候由于成本和电路结构…

充电桩运营平台的技术方案 53页

充电桩运营平台的技术方案 53页&#xff0c;全套解决方案 内容太多&#xff0c;复制图片丢失&#xff0c;需要完整的私信我。

图片kb太大了怎么改小?修改图片kb的方法介绍

图片kb太大了怎么改小&#xff1f;将图片的文件大小&#xff08;以KB为单位&#xff09;缩小可以带来多种优点&#xff0c;但也有一些缺点需要注意。缩小图片文件大小可以显著减少它在硬盘或其他存储设备上占用的空间&#xff0c;使你能够存储更多的图片和其他文件。而且&#…

Postman使用教程【项目实战】

目录 引言软件下载及安装项目开发流程1. 创建项目2. 创建集合(理解为&#xff1a;功能模块)3. 设置环境变量&#xff0c;4. 创建请求5. 测试脚本6. 响应分析7. 共享与协作 结语 引言 Postman 是一款功能强大的 API 开发工具&#xff0c;它可以帮助开发者测试、开发和调试 API。…

制造业中SCADA与MES系统承担着怎样的重任?

SCADA&#xff08;Supervisory Control and Data Acquisition&#xff09;是一种广泛应用于工业控制系统中的监控和数据采集系统。它主要用于监控和控制工业过程中的设备和活动&#xff0c;并收集相关数据以供分析和优化。SCADA系统由人机界面&#xff08;HMI&#xff09;、数据…

提醒我每天打卡的“目标打卡提醒软件”

在繁忙的生活中&#xff0c;我们总有许多需要每日坚持的习惯&#xff0c;无论是为了健康而设定的减肥计划&#xff0c;还是为了工作而必须的每日上班打卡&#xff0c;亦或是为了自我提升而规定的每日学习任务。这些日常打卡活动&#xff0c;虽然重要&#xff0c;但在忙碌和疲惫…