第十五章 图的BFS与拓扑序列

news2024/11/15 8:07:00

图的BFS与拓扑序列

  • 一、图的BFS
    • 1、思路
    • 2、模板
      • (1)问题
      • (2)代码模板
      • (3)代码解析
  • 二、拓扑序列
    • 引入:
    • 1、什么是拓扑序列?
    • 2、模板:
      • (1)问题:
      • (2)代码模板:
      • (3)模板分析:
      • (4)注意:
        • STL中的队列行不行?
        • 为什么这里的BFS不用标记?
        • 如何判断是否成功?

一、图的BFS

1、思路

在这里插入图片描述
上图中的遍历顺序就是以A为起点开始的广度优先搜索。先遍历距离A点最近的距离,然后再依次向外拓展。

2、模板

(1)问题

在这里插入图片描述
题目当中提到了最短路,同时每条边的权重都是1,同时在边权为1的情况下,我们的广度优先搜索是具备最短路的性质的。因此,我们采用BFS去做这道题。而最短路的证明,在前面讲解DFS和BFS的时候证明过,大家可以自行去看,这里附上链接:

同时,在该文章中,我还为大家介绍了,为什么BFS要用队列,如何保证搜到的是最短的等等常见问题:

DFS与BFS保姆级教学

(2)代码模板

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e5+10;
const int M=3e5+10;
int h[N],e[M],ne[M],idx;
int m[N];
int n,k;
void add(int x,int y)
{
    e[idx]=y;
    ne[idx]=h[x];
    h[x]=idx++;
}
int bfs()
{
    queue<int>q;
    q.push(1);
    m[1]=0;
    while(!q.empty())
    {
        for(int i=h[q.front()];i!=-1;i=ne[i])
        {
            if(m[e[i]]==-1)
            {
                m[e[i]]=m[q.front()]+1;
                q.push(e[i]);
            }
            if(e[i]==n)goto A;
        }
        q.pop();
    }
    A:
    return m[n];
}
int main()
{
    memset(h,-1,sizeof h);
    memset(m,-1,sizeof m);
    cin>>n>>k;
    for(int i=0;i<k;i++)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
    }
    cout<<bfs();
    return 0;
}

(3)代码解析

在这里插入图片描述

二、拓扑序列

引入:

在生活中,我们经常会遇到类似一下的场景。
在这里插入图片描述
我们想要去上学的话,我们必须完成前面的一系列任务。不起床,怎么吃饭呢?不穿衣服,怎么上学呢?(当然,正常人的话)
那么我们有一下两条路可走:

起床–》穿鞋–》穿衣服–》吃饭–》背书包–》上学
起床–》穿衣服–》穿鞋–》吃饭–》背书包–》上学

这两条路都可以走,所以这两条路线都是正确的,这就是拓扑序列

1、什么是拓扑序列?

在这里插入图片描述
简单的说,拓扑序列就是有顺序地去访问图中的点。按照我们刚才的例子,我们发现,当一个点没有被指向的时候,这个点就相当于没有限制的,那么我们就可以直接访问,类似于A和E。那么被指向的路线个数称作:入度。从该点指出的路线个数叫做:出度

比如:A点的入度为0,出度为1。D点的入度为2,出度为3。

所以,我们只有当某个点的入度是0的时候,才能够访问。

那么上图中,我们可以直接访问A和E,但是先访问谁都可以,因此拓扑序列并不唯一。例如上图中,我们可以写出一条可能的拓扑序列:

在这里插入图片描述

什么情况下没有拓扑序列呢?
我们看下面的情况;
在这里插入图片描述
当一个图中出现这种环的时候,我们是无法写出拓扑序列的,因为图中没有度为0的点,因此我们无从下手。

2、模板:

(1)问题:

在这里插入图片描述
很明显,我们想要写出一个拓扑序列,就要从一个入度为0的点开始,当我们访问结束后,就可以删除这个点以及和这个点相关的边,然后再找下一个入度为0的点。即:逐个击破!

部分过程如下图所示:
在这里插入图片描述
那么我们的思路就是先找到所有入度为0的点,然后通过BFS的逻辑,扫描该入度为零的点周围相连的点。为什么这样做呢?我们的目的就是通过BFS的扫描去删除该点所连的边。就如同上图中的D点。
我们通过D点,去扫描离他最近的CFG点,然后删除DC边,DF边,DG边。当删除以后,我们发现,C点从入度为1变成了入度为0,也就是说这个点可以访问了,那么我们让这个点进队。最后,我们发现这个队中的数据就是拓扑序列。具体的例子可以看图中左侧的红色字母序列。

(2)代码模板:

#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10,M=3*N;
int h[N],e[M],ne[M],q[N],d[N],idx;
int n,m;
void add(int x,int y)
{
    e[idx]=y,ne[idx]=h[x],h[x]=idx++;
}
bool topsort()
{
    int hh=0,tt=-1;
    for(int i=1;i<=n;i++)if(!d[i])q[++tt]=i;
    while(hh<=tt)
    {
        int front=q[hh++];
        for(int i=h[front];i!=-1;i=ne[i])
        {
            if(--d[e[i]]==0)q[++tt]=e[i];
        }
    }
    int size=tt+1;
    return size==n;
}
int main()
{
    memset(h,-1,sizeof h);
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        add(x,y),d[y]++;
    }
    if(!topsort())puts("-1");
    else
    {
        for(int i=0;i<n;i++)printf("%d ",q[i]);
    }
    
}

(3)模板分析:

在这里插入图片描述

(4)注意:

STL中的队列行不行?

这里不能使用STL中的队列,因为STL中的队列,会把队头真的删掉,但是我们知道,队列中的数据存储的是我们的答案,我们只能通过模拟队列的方式,伪删头部,即通过指针的偏移来删除。这样做的话,我们的答案是会被保留下来的。

为什么这里的BFS不用标记?

我们这里只是采用了BFS的思想,但不是真正的BFS,所以我们会发现如果一个点的入度大于1的话,那么这个点是会被重复遍历的。所以,并不是BFS。我们只是通过一个入度为0的点,去扫描与他相连的最近的点,从而达到删除边的效果,类似于BFS。

如何判断是否成功?

如果一个图是拓扑排序的话,那么我们能利用逐个击破的思路访问到每一个点,也就是说我们的每一个点都会入队。我们的尾部指针指向的是当前的尾部元素的下标。但是我们的头是从下标为0的点开始的。所以我们的元素个数等于尾部指针+1。比如,尾指针指向1,但是我们的元素有q[0],q[1],此时我们的个数是2。

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

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

相关文章

一张图搞懂微服务架构设计

前言 当前&#xff0c;微服务架构在很多公司都已经落地实施了&#xff0c;下面用一张图简要概述下微服务架构设计中常用组件。不能说已经使用微服务好几年了&#xff0c;结果对微服务架构没有一个整体的认知&#xff0c;一个只懂搬砖的程序员不是一个好码农! 流量入口Nginx 在…

Awesome Uplift Modeling【如何学习因果推断、因果机器学习和Uplift建模?All in here】

Awesome-Uplift-Model How to Apply Causal ML to Real Scene Modeling&#xff1f;How to learn Causal ML&#xff1f; Github项目地址&#xff1a;&#x1f449;https://github.com/JackHCC/Awesome-Uplift-Model&#x1f448; &#x1f449;https://github.com/JackHCC/…

汇编原理理论知识复习

书上重点内容 本篇博客整理老师课上强调的重点理论知识&#xff0c;以便复习备考&#xff0c;如有错误欢迎指正。 这门课主要讲CPU芯片与其他芯片&#xff08;内存芯片和I/O接口芯片&#xff09;之间交互。 一条指令的执行过程&#xff1a;取指&#xff08;从主存取到CPU寄…

(五)Vue之data与el的两种写法

文章目录el的两种写法data的两种写法Vue学习目录 上一篇&#xff1a;&#xff08;四&#xff09;Vue之数据绑定 容器&#xff1a; <div id"root"><h1>hello,{{name}}</h1></div>el的两种写法 (1).new Vue时候配置el属性。 new Vue({el:#r…

【C语言航路】第六站:指针初阶

目录 一、指针是什么 二、指针和指针类型 1.指针类型的意义 2.指针-整数 3.指针解引用 三、野指针 1.野指针的成因 &#xff08;1&#xff09;指针未初始化 &#xff08;2&#xff09;指针越界访问 &#xff08;3&#xff09;指针指向的空间释放 2.如何规避野指针 &a…

伸手运动想象训练与伸手抓取想象的关系

本研究旨在确定为期4周的目标导向性伸手&#xff08;抓取任务&#xff09;的运动想象训练&#xff08;MIT&#xff09;是否会以相同的方式影响伸手&#xff08;MIR&#xff09;和抓取&#xff08;MIG&#xff09;运动想象的皮质活动。试验过程中&#xff0c;我们在健康的年轻参…

基于未知环境下四旋飞行器运动规划应用研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

QT QDoubleSpinBox 浮点计数器控件(使用详解)

本文详细的介绍了QDoubleSpinBox控件的各种操作&#xff0c;例如&#xff1a;新建界面、获取数值、设置前后缀、设置最大/小值、设置显示精度、关联信号槽、优化信号、关联控件、文件源码、样式表等等操作。 本文是QT控件使用详解的第十五篇 QT QDoubleSpinBox 浮点计数器控件(…

【ArcGIS风暴】ArcGIS栅格影像去除黑边(背景值)方法汇总

文章目录 1. 数据加载时属性中设置去除黑边2. 应用setnull工具去除黑边3. 应用栅格计算器去除黑边4. 应用复制栅格工具去除黑边5. 应用影像分析去除黑边6. 应用镶嵌数据集去除黑边影像产生黑边的原因无外乎在设置无效值时,将无效值设成了0,而影像在导入软件进行渲染时,并没有…

制作一个简单HTML静态网页(HTML+CSS)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

TensorRT安装

本文是为了记录安装TensorRT过程中遇到的一些问题。 首先进入TensorRT下载页面&#xff0c;选择你要下载的TensorRT版本。 因为TensorRT不同的版本依赖于不同的cuda版本和cudnn版本。所以很多时候我们都是根据我们自己电脑的cuda版本和cudnn版本来决定要下载哪个TensorRT版本。…

[附源码]计算机毕业设计校园招聘系统设计Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

如何收到消息第一时间将网站置灰,难道让程序员上个线?

注意&#xff1a;文本不是讲如何将网站置灰的那个技术点&#xff0c;那个技术点之前汶川地震的时候说过。 本文不讲如何实现技术&#xff0c;而是讲如何在第一时间知道消息后&#xff0c;更快速的实现这个置灰需求的上线。 实现需求不是乐趣&#xff0c;指挥别人去实现需求才…

安全研究 # 二进制代码相似性检测综述

本文参考&#xff1a; [1]方磊,武泽慧,魏强.二进制代码相似性检测技术综述[J].计算机科学,2021,48(05):1-8. (信息工程大学数学工程与先进计算国家重点实验室, 国家重点研发课题,北大核心) 摘要 代码相似性检测常用于代码预测、知识产权保护和漏洞搜索等领域&#xff0c;可分为…

Numpy入门[11]——生成数组的函数

Numpy入门[11]——生成数组的函数 参考&#xff1a; https://ailearning.apachecn.org/ 使用Jupyter进行练习 import numpy as nparange arange 类似于Python中的 range 函数&#xff0c;只不过返回的不是列表&#xff0c;而是数组&#xff1a; arange(start, stop None, st…

Java并发编程—java内存模型2

文章目录重排序数据依赖性as-if-serial重排序对多线程的影响顺序一致性同步程序的顺序一致性效果同步/异步总线事务双重校验锁—————————————————————————————————— 重排序 数据依赖性 数据依赖不能进行重排序 as-if-serial as-if-seri…

[附源码]计算机毕业设计大学生心理健康测评系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Compressed Bloom Filters论文总结

Compressed Bloom Filters论文总结AbstractI. INTRODUCTIONII. COMPRESSED BLOOM FILTERS:THEORYA. Bloom FiltersB. Compressed Bloom FiltersIII. COMPRESSED BLOOM FILTERS:PRACTICEA. ExamplesIV. DELTA COMPRESSIONV. COUNTING BLOOM FILTERSVI. CONCLUSIONAbstract 我们…

Elasticsearch面试题

Elasticsearch面试题 1 为什么要使用Elasticsearch? 系统中的数据&#xff0c;随着业务的发展&#xff0c;时间的推移&#xff0c;将会非常多&#xff0c;而业务中往往采用模糊查询进行数据的搜索&#xff0c;而模糊查询会导致查询引擎放弃索引&#xff0c;导致系统查询数据…

C#/WPF/.NET 找到的程序集清单定义与程序集引用不匹配

vs 窗口报错 引发的异常:“System.Windows.Markup.XamlParseException”(位于 PresentationFramework.dll 中) “初始化“CircularGauge.CircularGaugeControl”时引发了异常。”&#xff0c;行号为“288”&#xff0c;行位置为“23”。代码位置报错 FileLoadException: 未能…