PTA 7-6 列出连通集

news/2025/3/11 2:46:19/

题目详情:

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

输入格式:

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

输出格式:

按照"{ v1​ v2​ ... vk​ }"的格式,每行输出一个连通集。先输出 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 }

题目解析 

  逐步分析

  首先,图的表示方式。顶点数n不超过10,可以用邻接表或者邻接矩阵。因为需要按编号递增的顺序访问邻接点,所以邻接表里的每个顶点的邻接点应该按升序排列。或者,在每次访问邻接点的时候,按从小到大的顺序遍历。例如,对于邻接矩阵来说,每个顶点x的所有邻接点,可以按顶点编号从小到大遍历,即从0到n-1依次检查是否有边相连。

  或者,邻接表的话,每个顶点的邻接点列表需要排序。例如,每次添加边的时候,把邻接点插入到正确的位置,保持列表的升序。或者,在生成邻接表之后,对每个顶点的邻接点列表进行排序。这一步很重要,因为DFS和BFS的遍历顺序必须按照邻接点的编号递增的顺序进行访问。所以,图的存储结构可能需要邻接表或者邻接矩阵,同时要保证遍历邻接点的顺序是递增的。

  例如,邻接矩阵的话,对于每个顶点,遍历时检查所有顶点,按照编号顺序依次访问是否有边相连。这可能比较方便,特别是当顶点数目较小的时候(n<=10)。这样,在处理每个顶点的时候,只需要从0到n-1遍历,检查是否相连,并且是否未被访问过。这样就能保证按照编号递增的顺序访问邻接点。

  那邻接矩阵可能更适合这个题目,因为处理顺序容易控制。比如,假设用邻接矩阵存储,那么每个顶点x的邻接点就是所有y满足matrix[x][y]为true,并且y按照从小到大排列。所以在遍历的时候,只需要从0到n-1循环,判断是否是邻接点,并且是否已访问过。

  所以,邻接矩阵可能更简单。

  整个流程应该是这样的:对于DFS和BFS各需要处理一次:初始化访问数组,所有顶点未被访问。然后,按照顶点编号从小到大(从0到n-1)的顺序,逐个检查顶点是否被访问。如果未被访问,则从该顶点开始进行DFS或BFS,并将访问到的顶点记录下来,形成一个连通集。这样就能保证每个连通分量都是从其中最小的顶点开始遍历,并且在遍历过程中,邻接点按照编号递增的顺序被访问。

  大致步骤如下:

      1. 读取输入n和m。

      2. 构建邻接矩阵。初始化n×n的二维数组,初始为false。然后读取m条边,将对应的两个顶点之间的边设为true。

      3. 进行DFS遍历:

              a. 初始化一个访问数组visited,所有元素初始为false。

              b. 按照顶点编号从小到大遍历每个顶点i:

                     i. 如果未被访问,则开始DFS遍历,并将结果记录为一个连通集。

                    ii. 在DFS过程中,将访问的顶点按顺序保存,并在结束后输出。

      4. 进行BFS遍历,同样的逻辑,但使用队列。

  推荐代码

  

#include <iostream>
#include <vector>
#include <queue>
using namespace std;void DFS(int v, vector<bool>& visited, const vector<vector<bool>>& adj, vector<int>& component) {visited[v] = true;component.push_back(v);for (int i = 0; i < adj.size(); ++i) {if (adj[v][i] && !visited[i]) {DFS(i, visited, adj, component);}}
}void BFS(int v, vector<bool>& visited, const vector<vector<bool>>& adj, vector<int>& component) {queue<int> q;q.push(v);visited[v] = true;component.push_back(v);while (!q.empty()) {int current = q.front();q.pop();for (int i = 0; i < adj.size(); ++i) {if (adj[current][i] && !visited[i]) {visited[i] = true;component.push_back(i);q.push(i);}}}
}int main() {int n, m;cin >> n >> m;vector<vector<bool>> adj(n, vector<bool>(n, false));for (int i = 0; i < m; ++i) {int u, v;cin >> u >> v;adj[u][v] = true;adj[v][u] = true;}// DFSvector<bool> visited(n, false);for (int i = 0; i < n; ++i) {if (!visited[i]) {vector<int> component;DFS(i, visited, adj, component);cout << "{ ";for (int v : component) {cout << v << " ";}cout << "}" << endl;}}// BFSvisited.assign(n, false);for (int i = 0; i < n; ++i) {if (!visited[i]) {vector<int> component;BFS(i, visited, adj, component);cout << "{ ";for (int v : component) {cout << v << " ";}cout << "}" << endl;}}return 0;
}

自我实现代码 

  

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>using namespace std;int n,m;
int g[15][15];
int vis[15];
vector<int>res;
queue<int>q;void dfs(int x)
{res.push_back(x);vis[x]=1;for(int i=1;i<=n;++i){if(g[x][i]==1&&!vis[i]){vis[i]=1;dfs(i);}}
}void bfs(int x)
{res.push_back(x);q.push(x);vis[x]=1;while(!q.empty()){int xx=q.front();q.pop();for(int i=1;i<=n;++i){if(g[xx][i]==1&&!vis[i]){res.push_back(i);vis[i]=1;q.push(i);}}}}int main()
{cin>>n>>m;int a,b;for(int i=1;i<=m;++i){cin>>a>>b;g[a+1][b+1]=1;g[b+1][a+1]=1;	}for(int i=1;i<=n;++i){if(!vis[i]){res.clear();dfs(i);cout<<"{";for(int i=0;i<res.size();++i){cout<<" "<<res[i]-1;}cout<<" }"<<endl;}}memset(vis,0,sizeof(vis));for(int i=1;i<=n;++i){if(!vis[i]){while(!q.empty())q.pop();res.clear();bfs(i);cout<<"{";for(int i=0;i<res.size();++i){cout<<" "<<res[i]-1;}cout<<" }"<<endl;}}return 0;
}


http://www.ppmy.cn/news/1578232.html

相关文章

分布式ID生成方案:数据库号段、Redis与第三方开源实现

分布式ID生成方案&#xff1a;数据库号段、Redis与第三方开源实现 引言 在分布式系统中&#xff0c;全局唯一ID生成是核心基础能力之一。本文针对三种主流分布式ID生成方案&#xff08;数据库号段模式、Redis方案、第三方开源框架&#xff09;进行解析&#xff0c;从实现原理…

23种设计模式简介

一、创建型&#xff08;5种&#xff09; 1.工厂方法 总店定义制作流程&#xff0c;分店各自实现特色披萨&#xff08;北京店-烤鸭披萨&#xff0c;上海店-蟹粉披萨&#xff09; 2.抽象工厂 套餐工厂&#xff08;家庭装含大披萨薯条&#xff0c;情侣装含双拼披萨红酒&#…

机器学习数学基础:42.AMOS 结构方程模型(SEM)分析的系统流程

该流程图完整呈现了 AMOS 结构方程模型&#xff08;SEM&#xff09;分析的系统流程&#xff0c;具体步骤及内涵如下&#xff1a; 1. 模型设定 基于理论基础或研究假设&#xff0c;构建结构方程模型的初始框架&#xff0c;明确潜变量与显变量的关系、测量模型&#xff08;因子…

【GPT入门】第8课 大语言模型的自洽性

【GPT入门】第8课 大语言模型的自洽性 1.自洽性概念2.代码&#xff08;观察执行结果&#xff09;3.自洽性核心思想 1.自洽性概念 大模型的自洽性&#xff08;self - consistency&#xff09;是指在推理阶段&#xff0c;大模型通过生成多个答案并选择出现频率最高的那个&#x…

openwrt路由系统------lua、uci的关系

1. Luci 的核心组成 (1) Lua 简介:Luci 的界面和逻辑几乎完全使用 Lua 脚本语言编写。Lua 是一种轻量级、高效的嵌入式脚本语言,适合在资源受限的路由器环境中运行。作用: 生成动态 Web 页面(与后端交互渲染 HTML)。处理用户提交的表单数据(如修改 Wi-Fi 密码)。调用系…

在uni-app中使用SQLite实现离线下数据同步:从封装到实践

场景&#xff1a; 在移动应用开发中&#xff0c;确保应用在无网络连接时仍能正常运行并进行数据同步至关重要。 对于uni-app开发者而言&#xff0c;SQLite是理想的本地存储解决方案&#xff0c;支持结构化数据的存储和检索。本文将介绍如何在uni-app项目中使用SQLite实现离线…

【AI学习从零至壹】Pytorch逻辑回归

Pytorch逻辑回归 线性回归简单线性回归的参数估计概率和似然的区别 最⼤似然估计似然函数对数似然函数 逻辑回归梯度下降法下⼭问题梯度与学习率学习率 梯度下降法的模拟与可视化学习率对梯度的影响学习率的最佳取值 梯度更新逻辑回归模型构建及训练流程 线性回归 线性回归的⽬…

创建Electron35 + vue3 + electron-builder项目,有很过坑,记录过程

环境&#xff1a; node v20.18.0 npm 11.1.0 用到的所有依赖&#xff1a; "dependencies": {"core-js": "^3.8.3","vue": "^3.2.13","vue-router": "^4.5.0"},"devDependencies": {"ba…