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

news2024/9/20 13:27:08

目录

一、拓扑排序介绍

定义

特点

实现方法(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.coloradmin.cn/o/2135959.html

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

相关文章

【传纸条 / NOIP / Google】

题目 代码&#xff08;还是我的好理解&#xff0c;(●◡●)&#xff09; #include <bits/stdc.h> using namespace std; const int N 55; int w[N][N]; int f[2*N][N][N]; int main() {int m, n;cin >> m >> n;for(int i 1; i < m; i){for(int j 1; j…

ASPCMS靶场漏洞复现

浏览器访问环境 1.进入后台管理 aspcms默认的后台登录地址为/admin_aspcms/index.asp 用户名&#xff1a;admin 密码&#xff1a;123456 2.点击扩展功能里面的幻灯片设置 3.在保存的时候抓包 抓包修改slideTextStatus参数为一句话木马 1%25><%25Eval(Request (chr(65…

【CSS】选择器(基本选择器、复合选择器、属性匹配选择器、结构伪类选择器、伪元素选择器)

选择器 引入方式基础选择器复合选择器属性匹配选择器结构伪类选择器伪元素选择器 引入方式 1&#xff1a;外联 <!-- css引入方式1&#xff1a;外联 外联与内嵌优先级相同&#xff0c;取决于加载顺序 --><link rel"stylesheet" href"./样式.css"…

基于SpringBoot+Vue的养老院管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

Spring Cloud常见面试题

1.请说说你用过Spring Cloud哪些组件&#xff1f;这些组件分别有什么作用&#xff1f; 1、注册中心&#xff1a;Eureka、Nacos、Zookeeper、Consul&#xff1b;&#xff08;服务注册&#xff09; 2、负载均衡&#xff1a;Ribbon、LoadBalancer&#xff1b;&#xff08;客户端的…

文件误删危机应对:数据恢复全解析

文件误删&#xff1a;数字化时代的隐形挑战 在数字化的浪潮中&#xff0c;文件已成为我们工作、学习和生活中不可或缺的一部分。它们记录着我们的思想、成果与回忆&#xff0c;是连接现实与虚拟世界的桥梁。然而&#xff0c;这份便捷与高效背后&#xff0c;却隐藏着文件误删这…

集群聊天服务器项目【C++】(三)muduo库的简单介绍

在上一讲中介绍了Json库的相关知识&#xff0c;本次接着介绍muduo库的相关内容&#xff0c;这些知识在本项目中都会使用到。 1.muduo库简介 muduo库顶层就是epoll&#xff08;IO复用技术&#xff09; Linux的pthread多线程&#xff0c;所以只能安装在Linux系统中。此外它依赖…

Transformer学习(4):位置编码 Positional Encoding

为什么需要位置编码 在自注意力编码中&#xff0c;所有 a a a的计算都并行同时执行得到对应的 b b b&#xff0c;可以并行就代表着 a a a之间是不存在先后顺序关系的&#xff0c;这存在问题。 在不使用位置编码时&#xff0c;将 a 2 a_2 a2​与 a 3 a_3 a3​的顺序打乱&#…

java项目之疫情下图书馆管理系统源码(springboot)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的疫情下图书馆管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息。 项目简介&#xff1a; 疫情下图书馆管理系…

实景三维赋能低空经济:探索天空之城的未来图景

在数字化转型的大潮中&#xff0c;低空经济作为新兴业态正逐渐崭露头角&#xff0c;它不仅拓宽了航空业的边界&#xff0c;也为智慧城市、应急救援、物流配送、旅游观光等领域带来了前所未有的发展机遇。而实景三维技术&#xff0c;作为地理信息与遥感领域的前沿科技&#xff0…

java环境配置 | 基础铺垫

cmd命令 dir : 罗列目录下所有的文件展示出来cd xx : 进入xx文件夹cd … 返回上一级cls : 清除屏幕内容exit : 退出命令提示窗口环境变量 就是存储某个应用路径的变量,通过这个变量可以快速访问到某个应用exe 为什么要配置环境变量? 我们想要在任意的目录下都可以打开指…

小琳AI课堂:o1系列模型

大家好&#xff0c;这里是小琳AI课堂&#xff01;今天我们一起来探索OpenAI最新发布的o1系列模型&#xff0c;这可是AI领域的一大突破哦&#xff01; OpenAI o1系列模型技术大揭秘 o1系列模型是基于强化学习&#xff08;RL&#xff09;训练的&#xff0c;包括o1-preview和o1-…

彩漩科技亮相企业出海峰会,展示智能办公新力量

近日&#xff0c;在北京市海淀区商务局的指导下&#xff0c;由中关村东升科技园联合创新企业科普联盟共同举办的企业出海峰会于北京成功举办。本次峰会以“出海新征程&#xff0c;企业新高度”为核心议题&#xff0c;深入探讨全球化背景下科技企业出海面临的机遇与挑战。通过汇…

IntelliJ IDE 插件开发 | (十二)自定义项目脚手架(上)

系列文章 本系列文章已收录到专栏&#xff0c;交流群号&#xff1a;689220994&#xff0c;也可点击链接加入。 前言 在开发创建一个新项目的时候&#xff0c;我们一般都会使用平台自带的脚手架&#xff0c;如下图所示&#xff1a; 或者是使用网页版&#xff1a; 尽管平台已经…

GoogleDrive中上传文件,Java整合操作

GoogleDrive使用ServiceAccount的授权方式&#xff1a;&#xff08;科学上网&#xff09; 1.在Google Cloud中查看自己的项目&#xff1a;Dashboard – My First Project – Google Cloud console&#xff0c;没有的话新建项目。默认名称&#xff1a;My First Project 2. 创建…

基于 WeChatFerry 的 Python 机器人框架WeChatRobot

WeChatRobot 一个基于 WeChatFerry 的 Python 机器人框架。 微信机器人&#xff0c;接入Gemini、ChatGPT、ChatGLM、讯飞星火、Tigerbot&#xff1b;成语接龙、天气预报、新闻摘要、定时任务 克隆项目&#xff1a; git clone https://github.com/lich0821/WeChatRobot.git …

计算机毕业设计 沉浸式戏曲文化体验系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

百年病态集论的症结:3000年不识伪≌直线段

黄小宁 公元前1100年中国人商高同周公的一段对话谈到了勾股定理说明人类认识几何学的直线段起码已有3000多年。 直角三角形⊿的斜边c&#xff5e;水平直角边a&#xff0c;即c经旋转和均匀压缩变换可变为a&#xff5e;c。3000年不识伪≌直线段使数学认定a经刚体运动变为附着在c…

rk3399 的 HDMI 热插拔的问题

问题&#xff1a; 客户的3399 的板子上&#xff0c;烧写ubuntu 发现&#xff0c; 没有热插拔。 测试情况&#xff1a; 系统在第一次烧写完成之后&#xff0c;是有热插拔的&#xff0c;但是第二次启动就没有了。 还有一个情况&#xff0c;就是 &#xff0c;如果我一开始 上电的…

[论文精读]Polarized message-passing in graph neural networks

论文网址&#xff1a;Polarized message-passing in graph neural networks - ScienceDirect 论文代码&#xff1a;he-tiantian/PMP-GNNs&#xff1a;极化消息传递图神经网络的 Pytorch 实现&#xff0c;发表在 Artificial Intelligence&#xff0c;2024 年。 (github.com) 英…