题目:

7-1 列出连通集 (30 分)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照 “ { v1, v2, v3, ... ,vk } ”的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

​1​​ v​2​​ ... v​k​​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

分析:

当读完这道题之后,很容易就能够知道我们需要做的两件事:①构建图  ②DFS遍历和BFS遍历

这里为了方便起见(同时数据量并不大),这里将采用邻接矩阵存储图。


代码:

对结构体结构的定义:

#define max 10
typedef int vertex_type;
typedef int edge_type;
typedef struct graph_matrix{
int n, e;//顶点数;边数
vertex_type vexs[max];//顶点一维数组
edge_type edges[max][max];//邻接矩阵二维数组,元素类型为vector<vertex_type>
}gm;

全局变量visit[]

//visit[]数组;全局变量
int visit[max] = {};

①构建图

//创建图
void create_gm(gm &gm)
{
cin>>gm.n>>gm.e;
memset(gm.edges, , sizeof(gm.edges));
for(int i=; i<gm.n; i++){
gm.vexs[i] = i;
} //输入边数据
int a, b;
for(int i=; i<gm.e; i++){
cin>>a>>b;
gm.edges[a][b] = ;
gm.edges[b][a] = ;
}
}

②DFS遍历

//深度优先
//id: 以id为起始点
void DFS(gm &gm, int id)
{
visit[id] = ;
cout<<id<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][id] == && visit[i] == ){
DFS(gm, i);
}
}
}

③BFS遍历

//宽度优先
void BFS(gm &gm, int id)
{
visit[id] = ;
queue<int> qu;
qu.push(id);
while(qu.size() != ){
int mark = qu.front();
qu.pop();
cout<<mark<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][mark] == && visit[i] == ){
visit[i] = ;
qu.push(i);
}
}
}
}

全部的代码:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std; #define max 10
typedef int vertex_type;
typedef int edge_type;
typedef struct graph_matrix{
int n, e;//顶点数;边数
vertex_type vexs[max];//顶点一维数组
edge_type edges[max][max];//邻接矩阵二维数组,元素类型为vector<vertex_type>
}gm; //函数声明
void create_gm(gm &gm);
void DFS(gm &gm, int id);
void BFS(gm &gm, int id); //visit[]数组;全局变量
int visit[max] = {}; int main()
{
gm gm;//定义一个叫做gm的邻接矩阵
create_gm(gm); //调用DFS遍历
for(int i=; i<gm.n; i++){
if(visit[i] == )continue;
cout<<"{ ";
DFS(gm ,i);
cout<<"}"<<endl;
} //重置visit[]数组
memset(visit, , sizeof(visit)); //调用BFS遍历
for(int i=; i<gm.n; i++){
if(visit[i] == ){
cout<<"{ ";
BFS(gm ,i);
cout<<"}"<<endl;
}
}
return ;
} //创建图
void create_gm(gm &gm)
{
cin>>gm.n>>gm.e;
memset(gm.edges, , sizeof(gm.edges));
for(int i=; i<gm.n; i++){
gm.vexs[i] = i;
} //输入边数据
int a, b;
for(int i=; i<gm.e; i++){
cin>>a>>b;
gm.edges[a][b] = ;
gm.edges[b][a] = ;
}
} //深度优先
void DFS(gm &gm, int id)
{
visit[id] = ;
cout<<id<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][id] == && visit[i] == ){
DFS(gm, i);
}
}
} //宽度优先
void BFS(gm &gm, int id)
{
visit[id] = ;
queue<int> qu;
qu.push(id);
while(qu.size() != ){
int mark = qu.front();
qu.pop();
cout<<mark<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][mark] == && visit[i] == ){
visit[i] = ;
qu.push(i);
}
}
}
}

ALL


总结:

在这个题目中主要是对之前在树章节中,对关于树的前序遍历(DFS)和层次遍历(BFS)的知识迁移。

① DFS往往会运用到来进行实现,而递归就是利用栈的一个实现方法,递归特性使算法代码简洁的同时,也使算法理解困难,

所以对于我这种初学者来说画图和动手实践是最好的学习方法。

例子:“走迷宫,你没有办法用分身术同时走进多叉道路中,不撞南墙不回头。”(来源自网络)

② BFS则是要运用到队列,程序流程相对于DFS来说更为清晰。

例子:“当你眼镜掉了,你趴在地上找,你总是会先摸靠近你的地方,如果没有,再摸远一点的地方。”(来源自网络)

如何对已有知识的新运用也是能力提升的一种,在此我也对DFS和BFS有了更深一层的理解。

嘻嘻:)

列出连通集(DFS及BFS遍历图) -- 数据结构的更多相关文章

  1. 图的DFS与BFS遍历

    一.图的基本概念 1.邻接点:对于无向图无v1 与v2之间有一条弧,则称v1与v2互为邻接点:对于有向图而言<v1,v2>代表有一条从v1到v2的弧,则称v2为v1的邻接点. 2.度:就是 ...

  2. 邻接矩阵实现图的存储,DFS,BFS遍历

    图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...

  3. 数据结构上机实验dfs&&bfs遍历图

    #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #inc ...

  4. DFS和BFS遍历的问题

    来自https://github.com/soulmachine/leetcode 广度优先搜索 输入数据:没有什么特征,不像dfs需要有递归的性质.如果是树/图,概率更大. 状态转换图:数或者DAG ...

  5. 判断图连通的三种方法——dfs,bfs,并查集

    Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...

  6. 图的bfs遍历模板(邻接矩阵存储和邻接表存储)

    bfs遍历图模板伪代码: bfs(u){ //遍历u所在的连通块 queue q; //将u入队 inq[u] = true; while (q非空){ //取出q的队首元素u进行访问 for (从u ...

  7. 数据结构(三十二)图的遍历(DFS、BFS)

    图的遍历和树的遍历类似.图的遍历是指从图中的某个顶点出发,对图中的所有顶点访问且仅访问一次的过程.通常有两种遍历次序方案:深度优先遍历和广度优先遍历. 一.深度优先遍历 深度优先遍历(Depth_Fi ...

  8. [数据结构]图的DFS和BFS的两种实现方式

    深度优先搜索 深度优先搜索,我们以无向图为例. 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发, ...

  9. PTA 2-1 列出连通集【DFS+BFS基础】

    给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N−1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1 ...

随机推荐

  1. Java多线程和并发(五),线程的状态

    目录 1.线程的六个状态 2.sleep和wait的区别 3.锁池(EntryList)和等待池(WaitSet) 4.notify和notifyall的区别 五.线程的状态 1.线程的六个状态 2. ...

  2. TTTTTTTTTTTT 百度之星D map+hash

    Problem D  Accepts: 2806  Submissions: 8458  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 6 ...

  3. 「SDOI2017」硬币游戏

    题目链接 问题分析 首先一个显然的做法就是建出AC自动机,然后高斯消元.但是这样的复杂度是\(O(n^3m^3)\)的. 我们发现其实只需要求AC自动机上\(n\)个状态的概率,而其余的概率是没有用的 ...

  4. oracle判断一个字段为空

    比如 insert into table a (a1,b1)values("a1",''); 对于这种情况,因为表里存的是'',其实是没有内容的,要查询这个字段,不能直接使用 se ...

  5. kill 与 killall和过滤后杀掉

    1.绝杀 kill -9 PID  杀掉单一进程  例如:kill -9 pid号   同意的 kill -s SIGKILL   这个强大和危险的命令迫使进程在运行时突然终止,进程在结束后不能自我清 ...

  6. C++入门经典-例3.21-goto语句实现循环

    1:代码如下: // 3.21.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...

  7. linux各种中文乱码解决办法整理

    2016年03月21日 15:52:05 阅读数:30812 远程登录服务器用vim在终端下编辑查看文件经常会遇见各种中文乱码问题.做如下设置可基本解决vim中文乱码问题 首先查看系统对中文的支持lo ...

  8. express node 框架介绍

    开篇先声明一个重点: 就是论文件模块的重要性,之前我一直以为 fs 模块不重要,后来遇到了问题,才发现我之前的自以为是是多么愚蠢的一件事,我现在知道了 fs 模块的重要性 fs 模块:用于对文件的操作 ...

  9. DB2日常管理

    执行时间最长的10条SQL语句(按时间降序排列),可保存为脚本方便调用:db2 "SELECT rows_read / (num_executions + 1) as avg_rows_re ...

  10. TNS:could not resolve the connect identifier specified解决办法

    添加环境变量解决:TNS_ADMIN ->> D:\OracleDB\product\11.2.0\dbhome_1\NETWORK\ADMIN