题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856
思路
求树的高度本质就是层次遍历树,遍历完后记录下最大的层数,所以可以改造BFS遍历树的算法来实现求解树的最大深度
代码+注释
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;
struct VNode{
int num; //编号
int visited; //访问记录
vector<int> list; //邻接表
};
int N;
struct VNode vnodes[10003];
deque<int> queue_;
vector<int> max_depth;
//DFS遍历,用来计算连通分量数目
void DFS_visit(int v){
vnodes[v].visited = 1;
for(int i=0; i<vnodes[v].list.size(); i++){
if(vnodes[vnodes[v].list[i]].visited == 0)
DFS_visit(vnodes[v].list[i]);
}
}
//判断是否所有节点都被访问了
int all_visited(){
/*
return 0: 还有节点未被访问
return 1: 所有节点都被访问
*/
for(int i=1; i<=N; i++){
if(vnodes[i].visited == 0)
return 0;
}
return 1;
}
//将所有节点的置为未被访问的状态
void clear_visited(){
for(int i=1; i<=N; i++){
vnodes[i].visited = 0;
}
}
int main(){
int n1, n2;
int temp;
cin >> N;
for(int i=1; i<=N; i++){
vnodes[i].num = i;
vnodes[i].visited = 0;
}
for(int i=1; i<=N-1; i++){
cin >> n1 >> n2;
vnodes[n1].list.push_back(n2);
vnodes[n2].list.push_back(n1);
}
int width = 1; //某层的节点数,第一层的节点数为1
int components = 1; //联通分量数目
int H=0; //深度
int Max = -1;
for(int v=1; v<=N; v++){//以每个节点为根节点,计算其深度H,最后比较出最大的H
clear_visited();
queue_.clear();
queue_.push_back(v);
width = 1;
H = 0;
//bfs开始
while(queue_.size()){
for(int i=0; i<width; i++){
temp = queue_.front();
queue_.pop_front();
vnodes[temp].visited = 1;
for(int i=0; i<vnodes[temp].list.size(); i++){
if(vnodes[vnodes[temp].list[i]].visited == 0)//孩子节点未被访问过,则入队列
queue_.push_back(vnodes[temp].list[i]);
}
}
//更新width
width = queue_.size();
if(queue_.size())
H ++;
}
if(all_visited() == 0){//如果有其他联通分量,转而求连通分量数目
for(int v=1; v<=N; v++){
if(vnodes[v].visited == 0){
components ++;
DFS_visit(v);
}
}
cout << "Error: " << components << " components" << endl;
return 0;
}
if(H > Max){
max_depth.clear();
max_depth.push_back(v);
Max = H;
}
else if(H == Max){
max_depth.push_back(v);
}
}
sort(max_depth.begin(), max_depth.end(), less<int>());
for(int i=0; i<max_depth.size(); i++)
cout << max_depth[i] << endl;
return 0;
}
与普通的BFS不同的是,在while循环里面多了一层for循环,而for循环的次数是每一层的节点数量width
,当for循环结束后,本层上的所有节点都被遍历完,并且下一层的所有节点都已经push进队列里。只有当每次遍历完一层后,才能对深度H进行加1。