1021 Deepest Root 带注释

题目链接: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

猜你喜欢

转载自blog.csdn.net/SingDanceRapBall/article/details/113872245