PAT 甲级 1021 Deepest Root dfs求连通分量+找出树的最大高度结点

PAT 甲级 1021 Deepest Root dfs求连通分量+找出树的最大高度结点_第1张图片
PAT 甲级 1021 Deepest Root dfs求连通分量+找出树的最大高度结点_第2张图片

思路:

这道题给出一个无向图,该图有n个结点和n-1条边,若图是连通图,则它一定是一棵树,那么我们就要求出树的每个结点的高度,找出高度最大的所有结点,把结点序号依次输出;若图不是连通图,我们就要求出其连通分量的个数cnt并输出。我们先用一次dfs找到从任意一个结点开始搜索到的最大高度的结点(可能不唯一,不过对结果没有影响),把这些结点放入集合set中,并从这个结点开始再进行一次dfs,再把高度最大的结点放入集合set中,最后集合中的元素就是高度最大的结点,依次输出即可。


为什么要dfs两次呢?因为可能存在如下情况:
PAT 甲级 1021 Deepest Root dfs求连通分量+找出树的最大高度结点_第3张图片
首先,我们dfs了1号结点,因为是一个树,所以一次dfs就完成了。
此时我们发现高度最高的是4号结点,高度为3,但对于这棵树来说,最高的结点明显是6,高度是4,所以我们需要从4号结点出发再进行一次dfs,此次找到的高度最高的结点就是最终结果。

代码如下:

#include
#include
#include
#define INF 0x3f3f3f3f
#define MAX 10005
using namespace std;

int visit[MAX];//访问数组
vector<int> adj[MAX];//图的邻接表
vector<int> temp;//存放临时结点
set<int> s;//存放最高结点的集合
int n;//n为结点个数
int maxl=-1;//当前的最大高度
set<int>::iterator it;//定义前向迭代器

void dfs(int node,int height){//dfs
    if(height>maxl){//若当前的结点高度大于maxl
        maxl=height;//最大高度更新为height
        temp.clear();//清空temp
        temp.push_back(node);//把高度最大的结点放入temp
    }else if(height==maxl){//若等于maxl
        temp.push_back(node);//则直接将该结点放入temp
    }
    visit[node]=1;//标记已访问
    for(int i=0;i<adj[node].size();i++){//访问与node邻接的结点
        if(visit[adj[node][i]]==0){//若没有访问过
            dfs(adj[node][i],height+1);
        }
    }
    return;
}


int main(){
   cin>>n;
   for(int i=0;i<MAX;i++){
       visit[i]=0;
   }
   int a,b;
   for(int i=0;i<n-1;i++){
       cin>>a>>b;
       adj[a].push_back(b);
       adj[b].push_back(a);
   }
   int cnt=0;//记录连通分量的个数
   int max_node;//记录第一次dfs找到的最大结点
   for(int i=1;i<=n;i++){
       if(visit[i]==0){
           dfs(i,1);
           if(i==1){//说明是第一次dfs
               if(temp.size()!=0){
                   max_node=temp[0];//找到最大高度的结点
               }
               for(int j=0;j<temp.size();j++){//把temp中的元素放入集合
                   s.insert(temp[j]);
               }
           }
           cnt++;
       }
   }
   if(cnt>1){//说明图不连通
       cout<<"Error: "<<cnt<<" components";
   }else{//说明是一棵连通的树
       temp.clear();
       maxl=-1;
       for(int i=0;i<MAX;i++){
           visit[i]=0;
       }
       dfs(max_node,1);//第二次dfs
       for(int i=0;i<temp.size();i++){
           s.insert(temp[i]);
       }
       for(it=s.begin();it!=s.end();it++){
           if(it==s.begin()){
               cout<<*it;
           }else{
               cout<<endl<<*it;
           }
       }
   }
   return 0;
}

你可能感兴趣的:(PAT,DFS,图的遍历)