【代码随想录训练营第42期 Day58打卡 - 图论Part8 - 拓扑排序

目录

一、拓扑排序介绍

定义

特点

实现方法(2种)

应用

二、题目与题解

题目:卡码网 117. 软件构建

题目链接

题解:拓扑排序 - Kahn算法(BFS)

三、小结

一、拓扑排序介绍

对于拓扑排序,可以看看b站这个视频了解一下基本原理:图-拓扑排序

定义

拓扑排序(Topological Sorting)是对有向无环图(Directed Acyclic Graph,简称DAG)进行排序的一种算法。在图论中,拓扑排序为一个线性序列,这个序列满足对于每一条有向边(u, v),u在序列中都出现在v之前。换句话说,拓扑排序是对有向图顶点的一种线性排序,使得对于每一条有向边(u, v),u在排序中都在v之前

特点

一、有向无环图:拓扑排序只适用于DAG,如果图中存在环,则无法进行拓扑排序。(故可以通过拓扑排序检查图中是否存在环)

二、线性序列:拓扑排序的结果是一个线性的序列,满足边的方向性要求。

三、唯一性:一个DAG可能有多个拓扑排序序列。

实现方法(2种)

  • Kahn算法(BFS)

    1. 计算所有顶点的入度。
    2. 将所有入度为0的顶点入队。
    3. 当队列非空时:
      • 从队列中取出一个顶点,将其添加到拓扑序列中。
      • 减少其所有出边指向的顶点的入度。
      • 如果某个顶点的入度变为0,将其入队。
  • 深度优先搜索(DFS)

    1. 对于每个顶点,如果它没有被访问过,从它开始进行深度优先搜索。
    2. 在DFS结束时,将该顶点添加到拓扑序列的开始位置。
    3. 重复上述过程,直到所有的顶点都被访问过。

应用

  1. 项目调度:(1)在项目管理中,确定任务执行的顺序,使得所有前置任务都完成后才开始后续任务。    (2)在敏捷开发或瀑布模型中,确定各个阶段的完成顺序。

  2. 课程安排:在大学课程设计中,确定课程的学习顺序,考虑到某些课程是其他课程的前提条件。

  3. 编译依赖:在编译大型软件项目时,确定源文件的编译顺序,以确保所有依赖关系都得到满足。

  4. 任务优先级:在操作系统中,确定进程或线程的执行顺序,考虑到某些任务必须在其他任务之后执行。

  5. 网站链接结构分析:确定网页之间的链接关系,用于搜索引擎优化或网站导航设计。

  6. 事件序列化:在日志分析中,确定事件发生的先后顺序,特别是当事件之间存在因果关系时。

  7. 文件依赖解析:在文件系统或版本控制系统中,确定文件修改的顺序,以避免冲突和错误。

  8. 有向无环图分析:在任何DAG(有向无环图)的分析中,确定顶点的一个线性序列,使得对于每一条有向边(u, v),u在序列中都出现在v之前。

  9. 层次结构排序:确定组织结构或分类层次中的元素的顺序,如公司员工、产品类别等。

二、题目与题解

题目:卡码网 117. 软件构建

题目链接

117. 软件构建 (kamacoder.com)

题目描述

某个大型软件项目的构建系统拥有 N 个文件,文件编号从 0 到 N - 1,在这些文件中,某些文件依赖于其他文件的内容,这意味着如果文件 A 依赖于文件 B,则必须在处理文件 A 之前处理文件 B (0 <= A, B <= N - 1)。请编写一个算法,用于确定文件处理的顺序。

输入描述

第一行输入两个正整数 N, M。表示 N 个文件之间拥有 M 条依赖关系。

后续 M 行,每行两个正整数 S 和 T,表示 T 文件依赖于 S 文件。

输出描述

输出共一行,如果能处理成功,则输出文件顺序,用空格隔开。 

如果不能成功处理(相互依赖),则输出 -1。

输入示例

5 4
0 1
0 2
1 3
2 4

输出示例

0 1 2 3 4

提示信息

文件依赖关系如下:

所以,文件处理的顺序除了示例中的顺序,还存在

0 2 4 1 3

0 2 1 3 4

等等合法的顺序。

数据范围:

0 <= N <= 10 ^ 5

1 <= M <= 10 ^ 9

每行末尾无空格。

题解:拓扑排序 - Kahn算法(BFS)

这题是拓扑排序一个基本的应用:文件依赖问题

Kahn算法的基本思路:

  1. 计算所有顶点的入度。
  2. 将所有入度为0的顶点入队。
  3. 当队列非空时:
    • 从队列中取出一个顶点,将其添加到拓扑序列中。
    • 减少其所有出边指向的顶点的入度。
    • 如果某个顶点的入度变为0,将其入队。

代码如下: 

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

int main()
{
    int n, m; // n表示文件数量,m表示依赖关系的数量
    cin >> n >> m;
    vector<int> inDegree(n, 0); // 初始化所有文件的入度为0

    // 使用哈希表存储文件依赖关系,键(key)为文件编号,值(value)为依赖于该文件的文件列表
    unordered_map<int, vector<int>> dependencies;
    vector<int> ans; // 用于存储拓扑排序的结果

    // 读取依赖关系并构建依赖图
    for (int i = 0; i < m; i++)
    {
        int s, t;
        cin >> s >> t;
        inDegree[t]++; // 文件t依赖于文件s,因此文件t的入度增加
        dependencies[s].push_back(t); // 记录文件s的依赖列表
    }

    // 初始化队列,将所有入度为0的文件加入队列
    queue<int> q;
    for (int i = 0; i < n; ++i)
    {
        if (inDegree[i] == 0)
        {
            q.push(i);
        }
    }

    // 进行拓扑排序
    while (!q.empty())
    {
        int cur = q.front(); // 取出当前入度为0的文件
        q.pop();
        ans.push_back(cur); // 将其加入拓扑排序结果中
        for (int next : dependencies[cur]) // 遍历当前文件依赖的所有文件
        {
            --inDegree[next]; // 减少依赖文件的入度
            if (inDegree[next] == 0) // 如果入度变为0,说明所有依赖的文件都已经处理过,可以将其加入队列
            {
                q.push(next);
            }
        }
    }

    // 检查是否所有文件都已处理,如果没有,说明存在循环依赖
    if (ans.size() == n)
    {
        // 输出拓扑排序结果
        for (int i = 0; i < ans.size(); ++i)
        {
            cout << ans[i];
            if (i < ans.size() - 1)
            {
                cout << " "; // 在文件编号之间添加空格,最后一个文件后不加空格(特别注意)
            }
        }
    }
    else // 如果结果集大小不等于文件数量,说明存在循环依赖
    {
        cout << -1 << endl;
    }
    return 0;
}

这题当然也可以通过DFS实现,即是采用递归的思路,这里就不过多介绍了。对于拓扑排序问题,一般选择Kahn算法。

三、小结

最近图论章节的难度较大,打卡有延误。不过训练营的打卡也快要结束了,后边会继续加油打卡!

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

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

相关文章

攻防世界 ics-05

ics-05 隐藏的变量传参&#xff0c;php弱类型比较 只有设备维护中心可以点击进去 查看源码&#xff0c;发现有个隐藏的超链接变量传参 看到变量传参&#xff0c;有可能存在文件包含漏洞读取源码&#xff0c;这个站是php的站&#xff0c;所以可以使用php伪协议读取源码 index.p…

Web 原生组件化方案:Web Components

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 Web 组件化是一种将Web应用的UI部分拆分成可复用的独立组件的架构方法。这种方法有助于提高代码的可维护性、可重用性和可测试性。 而Web Components 标准则提供了一套原生的API&#xff0c;允许开发者创建…

IDEA 通义灵码 插件使用体验

目录 前言 主要功能 演示代码 解释代码 生成单元测试 生成代码注释 生成优化建议 代码片段补全 总结 前言 自从 AI 技术开始大规模应用&#xff0c;老板就想让下面的牛马借助 AI 工具来提高编码效率&#xff0c;由于团队都没有在实际编码中深度使用过 AI 工具&#x…

视频推拉流/直播点播EasyDSS平台安装失败并报错“install mediaserver error”是什么原因?

TSINGSEE青犀视频推拉流/直播点播EasyDSS平台支持音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务&#xff0c;在应用场景中可实现视频直播、点播、转码、管理、录像、检索、时移回看等。此外&#xff0c;平台还支持用户自行上传视频文件&#xff0c;也可…

【物联网技术大作业】设计一个智能家居的应用场景

前言&#xff1a; 本人的物联网技术的期末大作业&#xff0c;希望对你有帮助。 目录 大作业设计题 &#xff08;1&#xff09;智能家居的概述。 &#xff08;2&#xff09;介绍智能家居应用。要求至少5个方面的应用&#xff0c;包括每个应用所采用的设备&#xff0c;性能&am…

【深度学习】神经网络-怎么分清DNN、CNN、RNN?

怎么分清DNN、CNN、RNN&#xff1f; 最“大”的概念是人工神经网络&#xff08;Artificial Neural Network, ANN&#xff09;&#xff0c;它是较为广泛的术语&#xff0c;通常指的是一类模拟生物神经网络的数学模型&#xff0c;其中包括神经元、权重和连接。在这个术语下&#…

【Redis】主从复制 - 源码

因为主从复制的过程很复杂, 同时核心逻辑主要集中在 replication.c 这个文件中, 避免篇幅过大, 所以将主从复制中涉及这个文件的代码集中到了另一篇文章。 在当前文章主要分析主从复制的大体代码逻辑, 如果需要了解整体的过程, 可以配合 Redis 主从复制 - relication 源码分析 …

iOS 知识点记录

王巍 博客地址&#xff1a;OneVs Den git地址&#xff1a;onevcat (Wei Wang) GitHub 江湖人称喵神&#xff0c;目前就职于line。喵神的博客涉及方面比较广, 有Obejctive-C, Swift, SwiftUI, Unity等等。博客内容很有深度&#xff0c;非常值得关注。 戴铭 博客地址&#xff1…

ESP32-WROOM-32 开篇(刚买)

简介 买了一个ESP32-WROOM-32模块的开发板, 记录板初上机细节。 模块简介 Look 连接PC 1. 解决驱动问题 https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tabdownloads 下载驱动, 如下图 解压缩下载的包&#xff0c; 然后电机64位的版本&#xff0c; 一直…

汽车无钥匙启动功能工作原理

移‌动管家无钥匙启动‌是一种科技化的汽车启动方式&#xff0c;它允许车主在不使用传统钥匙的情况下启动车辆。这种技术通过智能感应系统实现&#xff0c;车主只需携带智能钥匙&#xff0c;当靠近车辆时&#xff0c;车辆能够自动解锁并准备启动。启动车辆时&#xff0c;车主无…

友思特方案 | 搭建红外桥梁:嵌入式视觉接口助力红外热像仪传输

导读 为红外成像设备数据传输快速搭桥&#xff01;友思特嵌入式视觉接口能帮助用户快速享有 GigE Vision 协议优势&#xff0c;是红外成像设备视觉接口集成、开发高性能相机的高效快捷方案。 引言 红外热像仪作为一种非接触式设备&#xff0c;能够检测红外能量&#xff08;热量…

CSS实现前端布局更巧妙的方案!在 flex 布局中通过使用 margin 实现水平垂直居中以及其他常见的前端布局

在前端开发中&#xff0c;实现水平垂直居中一直是个热门话题。随着 CSS Flexbox 布局的普及&#xff0c;开发者们开始更多地使用 justify-content 和 align-items 这两个属性来解决这个问题。 然而&#xff0c;还有一种更加简洁、灵活的方式——使用 margin: auto; 来实现居中以…

Grafana面板-linux主机详情(使用标签过滤主机监控)

1. 采集器添加labels标签区分业务项目 targets添加labels &#xff08;模板中使用的project标签&#xff09; … targets: [‘xxxx:9100’] labels: project: app2targets: [‘xxxx:9100’] labels: project: app1 … 2. grafana面板套用 21902 模板 演示

UE5 阴影通道

Shadow Pass Switch节点中 Default代表模型遮罩的效果 Shadow代表阴影的生成遮罩效果

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…

从C语言过渡到C++

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;C &#x1f3c5;往期回顾&#x1f3c6;&#xff1a;单链表实现&#xff1a;从理论到代码-CSDN博客&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱的博客-CSDN博客 目录 ​…

HOT 100(七)栈、堆、贪心算法

一、栈 1、每日温度 使用单调递减栈来解决。主要思路是遍历temperatures数组&#xff0c;利用栈来存储还没有找到比当前温度高的天数的索引。当遇到比栈顶索引所对应温度更高的温度时&#xff0c;就可以确定当前这一天的温度比之前那一天高。索引的差值就是等待的天数。 求一…

Golang数据流处理:掌握Reader和Writer接口的技巧

Golang数据流处理&#xff1a;掌握Reader和Writer接口的技巧 引言理解Reader和Writer接口Reader接口的定义和基本方法Writer接口的定义和基本方法 Reader接口的深入探讨Reader接口的实现示例使用io.Reader读取文件内容从网络连接中读取数据 常用Reader类型及其应用场景strings.…

相图的科学应用,陶瓷材料创新

陶瓷材料因其优异的物理和化学性能&#xff0c;在航空航天、电子、生物医学等多个领域展现出广阔的应用前景。陶瓷材料的性能很大程度上取决于其微观结构&#xff0c;包括晶粒大小、相组成和分布。相图作为描述陶瓷材料在不同条件下的相变行为和相平衡关系的图表反映了陶瓷材料…

10年Python程序员教你多平台采集10万+电商数据【附实例】

10万级电商数据采集需要注意什么&#xff1f; 在进行10万级电商数据采集时&#xff0c;有许多关键因素需要注意&#xff1a; 1. 采集平台覆盖&#xff1a;确保可以覆盖主流的电商平台&#xff0c;如淘宝、天猫、京东、拼多多等。 2. 数据字段覆盖&#xff1a;检查是否可以对平…