树与图的广度优先遍历

17 篇文章 1 订阅
订阅专栏

目录

一、概念

二、操作说明

1.树与图的广度优先遍历

2.拓扑排序

三、例题实践

1.树与图的广度优先遍历

a.题目描述

b.解题思路

c.代码实现

2.拓扑排序

a.题目描述

b.解题思路

c.代码实现


一、概念

树与图的广度优先遍历:树与图的广度优先遍历对于一个节点x面对多条分支,重复把沿着每一条分支到达的下一节点都遍历,直至该节点所能到达的点都被遍历完。

拓扑排序:给定一张有向无环图,若一个由图中所有点构成的序列A满足:对于图中的每条边(x,y),x在A中都出现在y之前,则称A是该有向无环图顶点的一个拓扑序。求解序列A的过程就被称为拓扑排序。

注:有向无环图:在有向图中,从一个节点出发,最终回到它自身的路径被称为“环”。不存在环的有向图即为有向无环图

二、操作说明

1.树与图的广度优先遍历

遍历过程以图1到9为例。

图1
图2

 

图3

 

图4

 

 

 

图5
图6

 

 

图7

 

 

图8

 

图9
int bfs(){
    memset(d,-1,sizeof d); ///d数组存储根节点到各个节点的距离,初始为-1
    d[1]=0; ///根节点1其距离为0
    queue<int> q;
    q.push(1);
    
    while(q,size()){
        int qt=q.front();
        q.pop();
        
        for(int i=h[qt];i!=-1;i=ne[i]){
            int j=e[i];
            if(d[j]==-1){ ///j==-1说明未被遍历过
                d[j]=d[qt]+1; ///点j的距离等于当前点的距离加1
                q.push(j); ///加入点j到队列
            }
        }
    }
}

2.拓扑排序

拓扑排序方法,不断选择图中入度为0的节点x,然后把x连向的点入度减1。这样能确保起点都能比终点更早选出来。(拓扑序不一定唯一)

注:入度:在有向图中,以节点x为终点的有向边的条数被称为x的入度,以节点x为起点的有向边的条数被称为x的出度。

形式如图10到18所示。

图10
图11

 

图12

 

图13

 

图14

 

图15
图16

 

图17

 

 

图18

void topsort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        ///若点i的入度为0,则将点i加入队列中
        if(!d[i])   q.push(i); 
    }
    
    while(q.size()){
        int qt=q.front();
        q.pop();
        ///将入度为0的点qt加入a存储的拓扑序中
        a[++cnt]=qt; 
        for(int i=h[qt];i!=-1;i=ne[i]){
            int j=e[i];
            ///若点j的入度减1后,其入度为0,则将其加入队列中
            if(--d[j]==0)   q.push(j);
        }
    }
    
}

三、例题实践

1.树与图的广度优先遍历

a.题目描述

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环。

所有边的长度都是 1,点的编号为 1∼n。

请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。

输入格式

第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1 的边。

输出格式

输出一个整数,表示 1 号点到 n 号点的最短距离。

数据范围

1≤n,m≤1e5

输入样例:

4 5
1 2
2 3
3 4
1 3
1 4

输出样例:

1

b.解题思路

思路:广搜的同时,记录各个节点到节点1的距离

c.代码实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int N=1e5+10,M=2*N;

int h[N],e[N],ne[N],idx;
int d[N];
int n,m;
    
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int bfs(){
    memset(d,-1,sizeof d); ///d数组存储根节点到各个节点的距离
    d[1]=0; ///根节点1其距离为0
    queue<int> q;
    q.push(1);
    
    while(q,size()){
        int qt=q.front();
        q.pop();
        
        for(int i=h[qt];i!=-1;i=ne[i]){ ///遍历与点qt相连的点
            int j=e[i];
            if(d[j]==-1){ ///d[j]==-1说明未被遍历过
                d[j]=d[qt]+1; ///点j的距离等于当前点的距离加1
                q.push(j); ///加入点j到队列
            }
        }
    }
    return d[n]; ///返回点1到n的距离,若1无法到达n,返回-1符合要求
}

int main(){
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b); ///将a到b的边加入邻接表中
    }
    
    cout <<bfs() <<endl;
    
    return 0;
}

2.拓扑排序

a.题目描述

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

输入格式

第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)。

输出格式

共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

否则输出 −1。

数据范围

1≤n,m≤1e5

输入样例:

3 3
1 2
2 3
1 3

输出样例:

1 2 3

b.解题思路

思路:按题目要求计算拓扑序

c.代码实现

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

const int N=1e5+10,M=2*N;

int h[N],e[M],ne[M],idx;
int d[N],a[N],cnt;
int n,m;

void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

bool topsort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        ///若点i的入度为0,则将点i加入队列中
        if(!d[i])   q.push(i); 
    }
    
    while(q.size()){
        int qt=q.front();
        q.pop();
        ///将入度为0的点qt加入a存储的拓扑序中
        a[++cnt]=qt; 
        for(int i=h[qt];i!=-1;i=ne[i]){
            int j=e[i];
            ///若点j的入度减1后,其入度为0,则将其加入队列中
            if(--d[j]==0)   q.push(j);
        }
    }
    
    ///若该有向图的拓扑序存在,则a中存储的拓扑序中a[n]不为0
    if(a[n]!=0)    return true;
    else return false;
}

int main(){
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        d[b]++; ///点a可以到达b,故b的入度加1
    }
    if(topsort()){
        for(int i=1;i<=n;i++)    printf("%d ",a[i]);
    }
    else puts("-1");
    
    return 0;
}

JavaScript的深度优先遍历广度优先遍历算法示例
10-18
两种常见的遍历方法是深度优先遍历(Depth-First Search, DFS)和广度优先遍历(Breadth-First Search, BFS)。在JavaScript中,我们可以使用递归或非递归的方法来实现这两种遍历。 1. **深度优先遍历**: 深度...
搜索论-广度优先遍历
每天进步一点点!
12-06 1219
广度优先遍历
的(深度 + 广度优先遍历
最新发布
咸鱼势力登场
07-15 771
一、的存储[1.的特性 2.的分类 3.有向的储存结构] 二、的深度优先遍历的运用[的重心] 三、广度优先遍历的运用[中点的层次]
广度优先遍历(bfs)
goto_1600的博客
02-12 342
题目点这里 #include<iostream> #include<string.h> #include<queue> using namespace std; const int N=100010; int h[N],e[N],idx,ne[N]; int d[N]; int n,m; bool st[N]; int bfs() { memset(...
的深度优先遍历广度优先遍历
linjianshaonian_的博客
08-14 541
根据题意,是在这棵中,去掉某一个结点之后,剩余的所有连通块中最大的连通块中点的数量,而我们要求的是在这些所有结点中最小的。也就是最小的最大连通块中点的数量。
遍历-深度优先遍历广度优先遍历
陌上羽
04-13 1万+
深度优先遍历类似于的先序遍历。假设给定初态是中所有顶点均未被访问过,从中某一顶点vi出发遍历中的定义如下:首先访问出发点vi,并将其访问标志置为1;然后,从vi出发点依次搜索vi的每个邻接点vj。如vj未被访问过,则以vj为新的出发点继续进行深度优先搜索广度优先遍历,类似于的按层次遍历。设G是连通的,且G的初态是所有顶点均未被访问过。从G的任一顶点vi出发按广度优先搜索遍历的步...
js代码-二叉广度优先遍历
07-16
综上所述,JavaScript中的二叉广度优先遍历是通过队列实现的,它按照层次顺序访问的所有节点。理解并熟练掌握这一算法,对于处理与二叉相关的问题至关重要。在实际开发中,我们可以根据需求扩展这个基本实现,...
python实现的深度优先遍历广度优先遍历详解
09-18
本篇文章将深入探讨两种主要的遍历方法:深度优先遍历(DFS,Depth-First Search)和广度优先遍历(BFS,Breadth-First Search),并介绍如何在Python中实现它们。 **深度优先遍历** 是一种沿着的深度尽可能深...
python基础编程:python实现的深度优先遍历广度优先遍历详解
01-20
本文实例讲述了python实现的深度优先遍历广度优先遍历。分享给大家供大家参考,具体如下: 广度优先(层次遍历) 从的root开始,从上到下从左到右遍历整个的节点 数和二叉的区别就是,二叉只有左右两个...
C# 广度优先遍历(BFS)算法实现
01-06
那么广度遍历的顺序就是ABCDEF 从上到下,从左到右去访问 运用到格子游戏中,找寻某点到某点的路径 【假设只记录四方位(遍历顺序上左下右)】 向队列中存入起点,遍历该点周围的点,边界看做障碍,遍历到结束点返回...
算法基础之搜索论——广度优先遍历
qq_48813213的博客
03-28 232
题目:中点的层次 给定一个 n 个点 m 条边的有向中可能存在重边和自环。 所有边的长度都是 1,点的编号为 1∼n。 请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1 的边。 输出格式 输出一个整数,表示 1 号点到 n 号点的最短距离。 数据范围 1≤n,m≤10^5 输入样例: 4 5 1 2 2 3 3 4 1 3 1
广度优先搜索算法并生成BFS
热门推荐
不能说的秘密的博客
12-04 1万+
笔者在前面的两篇文章中介绍了的两种实现方法: 的邻接表的实现 的邻接矩阵的实现 接下来笔者将介绍遍历算法
【3.搜索-模板】4.广度优先遍历(模板)
qq_52384627的博客
08-10 128
1.中点的层次 #include <cstring> #include <iostream> using namespace std; const int N=1e5+10; int h[N], e[N], idx, ne[N];//e[i]存储中的下标 int d[N]; //存储每个节点离起点的距离 d[1]=0 int n, m; //n个节点m条边 int q[N]; //存储层次遍历序列 0号节点是编号为1的节点 /* 4 5 1 2 2 3 3 4 1 3
广度优先遍历(中点的层次)
。。。
09-15 264
的bfs
理解广度优先遍历遍历策略解析
在计算机科学中,广度优先遍历(Breadth-First Search,简称BFS)是一种用于遍历搜索算法。这个算法从根节点开始,然后遍历所有相邻的节点,接着对每个相邻节点进行同样的操作,直到遍历完所有节点。在...
写文章

热门文章

  • DFS学习总结 2350
  • 辗转相除法原理小结 1760
  • 树与图的深度优先遍历 1725
  • 倒水问题——DFS 1158
  • DP——背包 1104

分类专栏

  • 小白月赛 7篇
  • CFdiv3题解 9篇
  • CFdiv2 2篇
  • ABC 7篇
  • CFdiv1+div2 1篇
  • CFdiv4题解 1篇
  • 杂题 1篇
  • 题解 11篇
  • 总结 17篇

最新文章

  • 牛客小白月赛77 C题题解
  • Codeforces Round 811 (Div. 3)G题题解
  • Codeforces Round 893 (Div. 2)B题题解
2023年28篇
2022年27篇
2021年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家工业玻璃钢雕塑摆件销售厂家儿童区商场美陈玻璃钢七星瓢虫雕塑新民玻璃钢头像雕塑盐城玻璃钢人物雕塑矿工玻璃钢雕塑厂家红色大玻璃钢花盆天津水果玻璃钢雕塑价位青浦玻璃钢雕塑宝山区玻璃钢雕塑信息推荐玻璃钢动物雕塑长凳辽宁商场主题创意商业美陈思路佳木斯玻璃钢雕塑生产厂家上海玻璃钢雕塑艺术厂江门透明玻璃钢雕塑摆件湖南玻璃钢浮雕室外抽象雕塑厂家商场国庆美陈活动方案rtm法玻璃钢雕塑设计划算的玻璃钢卡通雕塑铸铜玻璃钢卡通雕塑设计莱阳玻璃钢花盆花器晋中玻璃钢花盆花器昆明承德玻璃钢卡通雕塑上海市玻璃钢雕塑生产厂家大型玻璃钢雕塑过程江苏商场玻璃钢雕塑设计厂家于洪玻璃钢花盆花器佛山玻璃钢动物牛雕塑河北户外商场美陈多少钱普洱玻璃钢雕塑设计怎么样香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化