问题描述
已知无向图的邻接矩阵,以该矩阵为基础,给出深度优先搜索遍历序列,并且给出该无向图的连通分量的个数。
在遍历时,当有多个点可选时,优先选择编号小的顶点。(即从顶点1开始进行遍历)
输入格式
第一行是1个正整数,为顶点个数n(n<100),顶点编号依次为1,2,…,n。
后面是邻接矩阵,n行n列。
输出格式
共2行。
第一行输出为无向图的深度优先搜索遍历序列,输出为顶点编号,顶点编号之间用空格隔开;
第二行为无向图的连通分量的个数。
样例输入
6
0 1 0 0 0 0
1 0 0 0 1 0
0 0 0 1 0 0
0 0 1 0 0 0
0 1 0 0 0 1
0 0 0 0 1 0
样例输出
1 2 5 6 3 4
2
深度优先遍历的代码如下:
#include <bits/stdc++.h>
using namespace std;
int a[101][101],vis[101]={0};//a是邻接矩阵数组,vis是标记结点是否访问过
int n,cnt=0; //cnt记录联通向量个数
void dfs(int node){
cout << node << " ";
vis[node]=1; //标记已访问过
for(int i=1;i<=n;i++){
if(a[node][i] && !vis[i]) //如果两节点有边而且未访问过
dfs(i); //继续往下搜
}
}
int dfstraverse(int node){
for(int i=1;i<=n;i++){ //确保每个结点都能访问到
if(!vis[i]){
dfs(i);
cnt++; //每一次dfs对应一个联通向量,这里其实还挺好理解的
} //你想如果一个结点可以一直深搜下去,那它肯定只有一个
} //联通分量。但是如果断了,回溯了,
return cnt; //比如此题中的1256之后的3,就是一个新的分支
} //从它深搜下去,就是一个新的联通向量
int main(){
cin >> n;
for(int i=1;i<=n;i++){ //因为它从结点1开始所以从下标1开始存
for(int j=1;j<=n;j++){
cin >> a[i][j];
}
}
dfstraverse(1);
cout << endl << dfstraverse(1);
return 0;
}
广度优先类似于树的层序遍历,而树的层序遍历我们借助了队列这个数据结构,所以图的广度优先也可以借助队列来实现,代码如下:
void bfstraverse(){
for(int i=1;i<=n;i++){ //确保每一个结点访问到
if(!vis[i]){
vis[i]=1; //标记已访问过
q.push(i); //此结点入队列
while(!q.empty()){
int value = q.front();
cout << value << " ";//打印队头结点
q.pop(); //队头结点出队列
for(int j=1;j<=n;j++){
if(a[value][j] && !vis[j]){ //找到与对头结点有边的结点
q.push(j); //依次入队列
vis[j]=1; //标记已访问
} //此后会进入入队出队的循环知道一个
} //联通向量遍历结束
} //之后进入for循环开始找另外的联通向量
}
}
}
不过联通向量个数好像只能通过dfs以及并查集来实现,bfs应该不行吧(反正我没有搜到),所以广度优先实现时的求解联通向量个数还是参考dfs的代码。如果还有更好的方法,请大佬多多指教。