Description
给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列。(同一个结点的同层邻接点,节点编号小的优先遍历)
Input
输入第一行为整数n(0< n <100),表示数据的组数。
对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),表示有m条边,k个顶点,t为遍历的起始顶点。
下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。
Output
输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示BFS的遍历结果。
Sample
Input
1
6 7 0
0 3
0 4
1 4
1 5
2 3
2 4
3 5
Output
0 3 4 2 5 1
Hint
以邻接矩阵作为存储结构。
两种实现方法:
第一种做法:非递归实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct map {
int vex[101];//顶点数组
int arc[101][101];//边数组
} MGraph;
int u, v; //表示一条连接u,v顶点的无向边。
void BFS(MGraph G, int k, int m, int t) {
//给顶点赋值
for(int i = 0; i < k; i++) {
G.vex[i] = i;
}
//矩阵初始化
for(int i = 0; i < k; i++) {
for(int j = 0; j < k; j++) {
G.arc[i][j] = 0;
}
}
//构造关系网
for(int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
G.arc[u][v] = G.arc[v][u] = 1;
}
int visited[101] = {0};//访问数组
int q[500] = {-1}; //队列数组
int in = 0; //队列存进下标
int out = 0; //队列弹出下标
int i, j;
int len = 0; //队列中的元素个数
// for(i = 0; i < k; i++) { //对每一个顶点做循环(若是说明连通图,可以不用循环)
i = t; //起始顶点//因为是连通图,所以不需要用循环
//for循环的作用:防止图有单独的子图或着单个的点遗漏,所以用循环检查
if(visited[i] == 0) { //如果当前顶点没有被访问过则对它进行访问
visited[i] = 1; //做标记
printf("%d", G.vex[i]); //打印顶点(第一个)
q[in] = i; //用队列保存当前顶点下标
in++;
len++;
while(len != 0) {
i = q[out]; //队列元素出队列,赋值给i(i的值变为对应的顶点下标)
out++;
len--;//元素出队列,个数减一
for(j = 0; j < k; j++) {//利用for循环,查找与当前顶点相连并且没有被访问过的顶点
//此循环相当于找到与当前顶点相连且没有访问过的顶点,并将其下标存入队列中
//当下一次while循环时相当于从队列中取出的顶点开始,重复同样的操作
//直到每一个顶点都被访问完(因为是连通图,所以能找到所有的顶点),队列中不再存有
//顶点下标,元素个数变为0,此时结束循环。
if(G.arc[i][j] == 1 && visited[j] == 0) {
visited[j] = 1;//标记找到的顶点
printf(" %d", G.vex[j]); //打印顶点//将相连但没被访问过的打印出来
q[in] = j;//将找到的顶点下标入队列
in++;
len++;//元素进队列,个数加一
}
}
}
}
// }
}
//非递归实现
//可行代码
int main() {
int n;
scanf("%d", &n);
int k;//顶点
int m;//边数
int t;//遍历起始顶点
while(n--) {
scanf("%d%d%d", &k, &m, &t);
MGraph G;
BFS(G, k, m, t);
}
return 0;
}
第二种做法:递归实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//BFS递归实现
int map[220][220];//边数组
int vis[220];//访问数组
int ans[220];//顶点数组
int a = 0;
int b = 1;
int k, t;
//没有预先建立顶点数组,因为只要求打印顶点编号所以用顶点下标来
//表示顶点,并且在遍历的同时给顶点数组赋值
void BFS(int t) {
a++;
for(int i = 0; i < k; i++) {
//通过循环遍历与当前开始顶点 n 相连的顶点,并且
//将满足相连且没被访问过的顶点存入顶点数组。对遍历
//好的顶点进行标记
if(map[t][i] == 1 && vis[i] == 0) {
//[b++],b先被用再++;
ans[b++] = i; //给顶点数组赋值
vis[i] = 1; //对已访问顶点标记
}
}
//将与当前开始顶点相连且没被访问过的顶点获取之后,将获取的 邻接顶点 又做为
//新的开始顶点重复同样操作。
//如果a小于等于b表示获取到的邻接顶点还没有全部作为开始顶点重复操作完,递归进行重复操作
if(a <= b)
BFS(ans[a]);
//退出递归的条件就是每一个顶点都被访问完,此时再没有满足“没有访问过”这个条件
//的邻接顶点,b不再递增,而a递增访问,当a大过b时递归结束
}
int main() {
int n, m, u, v, i;
scanf("%d", &n);
while(n--) {
memset(map, 0, sizeof(map));
memset(vis, 0, sizeof(vis));
scanf("%d%d%d", &k, &m, &t);
//建立边关系
for(i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
//对称矩阵
map[u][v] = map[v][u] = 1;
}
ans[0] = t; //顶点数组赋初值(遍历开始顶点)
vis[t] = 1; //标记开始数组
BFS(t);
for(i = 0; i < b; i++) {
printf("%d%c", ans[i], i == b - 1 ? '\n' : ' ');
}
}
return 0;
}