给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用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 }
由于缺少相关的知识点和练习,我在解这道题的过程非常的坎坷,首先第一个难住我的就是不连通的图如何方便的进行搜索,我于是使用集合来储存访问过的点,然后从0开始遍历,遇到不在集合的就以它为起点进行搜索,后来发现在进行广度优先搜索时出现死循环,发现原来时start没有重置,以后写代码时候要注意更改就要一起改,这我更深切的体会的函数的好处,可以有效避免这种情况发生,再就是集合的运用不太熟练,忘记了find的用法。
此外初始化每个节点与自己相连可以说时点睛之笔了,以后做有关图相关的可以参考
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
// 比较函数,用于排序
bool cmp(int a, int b) {
return a < b;
}
// 深度优先搜索函数
void dfs(vector<vector<int>>& graph, vector<bool>& visited, int start, set<int>& s) {
cout << start << " "; // 输出当前节点
s.insert(start); // 将已经访问过的节点保存到集合中
visited[start] = true; // 将当前节点标记为已访问
// 遍历当前节点的邻居节点
for (unsigned int i = 0; i < graph[start].size(); i++) {
int next = graph[start][i];
// 如果邻居节点未被访问过,则继续深度优先搜索
if (!visited[next]) {
dfs(graph, visited, next, s);
}
}
}
// 广度优先搜索函数
void bfs(vector<vector<int>> graph, vector<bool>& visited, int start, set<int>& s) {
queue<int> q;
q.push(start); // 将起始节点加入队列
visited[start] = true; // 将起始节点标记为已访问
while (!q.empty()) {
int current = q.front(); // 获取队列头部节点
cout << current << " "; // 输出当前节点
s.insert(current); // 将已经访问过的节点保存到集合中
q.pop(); // 弹出队列头部节点
// 遍历当前节点的邻居节点
for (unsigned int i = 0; i < graph[current].size(); i++) {
int next = graph[current][i];
// 如果邻居节点未被访问过,则加入队列并标记为已访问
if (!visited[next]) {
q.push(next);
visited[next] = true;
}
}
}
}
int main() {
int n, e;
cin >> n >> e; // 输入节点数和边数
set<int> s; // 保存深度优先搜索的结果
vector<vector<int>> graph(n); // 图的邻接表表示
vector<bool> visited(n, false); // 记录节点是否被访问过的标记数组
// 初始化每个顶点都与自己相连
for (int i = 0; i < n; i++) {
graph[i].push_back(i);
}
// 输入边的信息并构建图的邻接表
for (int i = 0; i < e; i++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
// 对邻接表中的每个列表进行排序
for (int i = 0; i < n; i++) {
sort(graph[i].begin(), graph[i].end(), cmp);
}
int start;
// 对每个未被访问过的节点进行深度优先搜索
for (int i = 0; i < n; i++) {
if (s.find(i) != s.end()) {
continue; // 如果节点已被访问过,则跳过
} else {
start = i; // 记录当前起始节点
cout << "{ ";
dfs(graph, visited, start, s); // 进行深度优先搜索
cout << "}" << endl;
}
}
set<int> s1; // 保存广度优先搜索的结果
visited = vector<bool>(n, false); // 重置节点访问标记数组
// 对每个未被访问过的节点进行广度优先搜索
for (int i = 0; i < n; i++) {
if (s1.find(i) != s1.end()) {
continue; // 如果节点已被访问过,则跳过
} else {
start = i; // 记录当前起始节点
cout << "{ ";
bfs(graph, visited, start, s1); // 进行广度优先搜索
cout << "}" << endl;
}
}
return 0;
}