题目
给定一个有n
个顶点和m
条边的无向图,请用深度优先遍历(DFS)和广度优先遍历(BFS)分别列出其所有的连通集。假设顶点从0
到n−1
编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1
行给出2
个整数n (0<n≤10)
和m
,分别是图的顶点数和边数。随后m
行,每行给出一条边的两个端点。每行中的数字之间用1
空格分隔。
输出格式:
按照"{ v1v_1v1 v2v_2v2 … vkv_kvk }"的格式,每行输出一个连通集。先输出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 }
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
栈限制 8192 KB
思路
- 用邻接矩阵存储图
- 分别进行深搜与广搜
代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int a[10][10],am[10][10];//a用来储存邻接矩阵am是a的拷贝
int f[10];//标记这个端点有没有被temp放入过
int n,m;//图的顶点数与边数
typedef vector<int> vint;
typedef vector<vint> vvint;
vint temp;//记录联通集
queue<int> Q;//队列负责进行BFS
void dfs(int v){//深搜代码
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
am[i][j] = a[i][j];
}
}//用am拷贝a(变成一个函数调用好像更好)
f[v] = 0;//声明此顶点已经被访问过了
temp.push_back(v);
for(int i = 0;i < n;i++){
if(f[i] && a[v][i]){//当找到与v连接并没有被放入过temp的顶点后
am[v][i] = 0;
am[i][v] = 0;//把边取消(没用)
dfs(i);//(递归,一条路走到黑)
}
}
}
void bfs(int v){//广搜代码
int top;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
am[i][j] = a[i][j];
}
}//用am拷贝a
f[v] = 0;//声明此顶点已经被访问过了
Q.push(v);//放入队列
while(!Q.empty()){//当队列非空(队列空说明找完了)
top = Q.front();//找到最靠前的顶点(泼水时目前的水源)
Q.pop();
temp.push_back(top);
for(int i = 0;i < n;i++){//从水源出发找能渗进去的顶点
if(f[i] && am[top][i]){
Q.push(i);
f[i] = 0;
}
}
}
}
int main(void){
int x,y;
vvint d,b;
cin >> n >> m;
for(int i = 0;i < n;i++){//初始化
for(int j = 0; j < n;j++){
a[i][j] = 0;
}
f[i] = 1;
}
for(int i = 0;i < m;i++){//标边
cin >> x >> y;
a[x][y] = 1;
a[y][x] = 1;
}
for(int i = 0;i < n;i++){//dfs
if(f[i]){
temp.clear();
dfs(i);
d.push_back(temp);
}
}
for(int i = 0;i < n;i++){//复原f
f[i] = 1;
}
for(int i = 0;i < n;i++){//bfs
if(f[i]){
temp.clear();
bfs(i);
b.push_back(temp);
}
}
for(int i = 0;i < d.size();i++){
cout << "{ ";
for(int j = 0;j < d[i].size();j++){
cout << d[i][j] << ' ';
}
cout << '}' << endl;
}//打印DFS
for(int i = 0;i < b.size();i++){
cout << "{ ";
for(int j = 0;j < b[i].size();j++){
cout << b[i][j] << ' ';
}
cout << '}' << endl;
}//打印BFS
return 0;
}
复盘
am数组好像没有必要,不将a数组作为全局变量而是放在main函数里就省掉了拷贝的过程
感觉用邻接表好像遍历的会快一点(也许?