题目描述
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
输出格式
按照"{ }"的格式,每行输出一个连通集。先输出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 模板。
DFS:
传入参数:
- 邻接矩阵或邻接表存图、待访问结点、访问数组
算法描述:
- 访问结点,标记为访问过
- 用一重循环访问该结点的邻接点
- 如果未访问过,递归调用 DFS 访问该邻接点
BFS:
传入参数:
- 邻接矩阵或邻接表存图、待访问结点、访问数组
算法描述:
- 访问结点,标记为访问过,结点入队
- 如果队列非空,循环:
- 结点出队,用一重循环访问该结点的邻接点
- 如果未访问过,访问结点,标记为访问过,结点入队
为了简化代码使用的技巧:
- 简易队列
- front 指向队首元素,rear 指向队尾待插入空位。
- 队列为空:front == rear
- 入队:queue[rear++] = x;
- 出队:x = queue[front++];
#include <stdio.h>
int front, rear, queue[10];
void BuildGraph(int G[][10], int e)
{
int i, a, b;
for (i = 0; i < e; i++) {
scanf("%d %d", &a, &b);
G[a][b] = G[b][a] = 1;
}
}
void DFS(int G[][10], int n, int v, int *visited)
{
printf("%d ", v);
visited[v] = 1;
for (int i = 0; i < n; i++)
if (!visited[i] && G[v][i])
DFS(G, n, i, visited);
}
void BFS(int G[][10], int n, int v, int *visited)
{
printf("%d ", v);
visited[v] = 1;
front = 0; rear = 0;
queue[rear++] = v;
while (front != rear) {
v = queue[front++];
for (int i = 0; i < n; i++) {
if (!visited[i] && G[v][i]) {
printf("%d ", i);
visited[i] = 1;
queue[rear++] = i;
}
}
}
}
void PrintDFS(int G[][10], int n, int *visited)
{
int i;
for (i = 0; i < n; i++) visited[i] = 0;
for (i = 0; i < n; i++) {
if (!visited[i]) {
printf("{ ");
DFS(G, n, i, visited);
printf("}\n");
}
}
}
void PrintBFS(int G[][10], int n, int *visited)
{
int i;
for (i = 0; i < n; i++) visited[i] = 0;
for (i = 0; i < n; i++) {
if (!visited[i]) {
printf("{ ");
BFS(G, n, i, visited);
printf("}\n");
}
}
}
int main()
{
int n, e;
int G[10][10] = {0}, visited[10];
scanf("%d %d", &n, &e);
BuildGraph(G, e);
PrintDFS(G, n, visited);
PrintBFS(G, n, visited);
return 0;
}