1021 Deepest Root (25 point(s))
A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤104) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each describes an edge by given the two adjacent nodes' numbers.
Output Specification:
For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print Error: K components
where K
is the number of connected components in the graph.
Sample Input 1:
5
1 2
1 3
1 4
2 5
Sample Output 1:
3
4
5
Sample Input 2:
5
1 3
1 4
2 5
3 4
Sample Output 2:
Error: 2 components
考察知识点:连通分支、DFS
注意点:
1. 并查集求连通分支的方法;
2. 图的存储方法;
3. DFS求树的深度以及各结点所在的层次
思路:
先给出结论,一棵有N个结点的树,一定有N-1条边(离散数学中有证明)。因此,首先用并查集来计算连通分支数,如果不连通输出,否则说明这一定是一棵树,没有环。
下一个任务是确定以哪一个结点为根,树有最大的深度。采用遍历每一个结点的方法,暴力求解,问题转化为已知根节点求树的深度。用数组visit[]、level[]分别记录第i个结点是否已经被访问以及所在的层次,使用DFS搜索。
参考大神链接:https://blog.youkuaiyun.com/richenyunqi/article/details/79551890
图相关的题目在近几年PAT-A中越来越多,需要重视!
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
using namespace std;
const int MAX = 1e4+7;
int Tree[MAX];
int findRoot(int x){//寻找根结点
if(Tree[x]==-1) return x;
else{
int temp = findRoot(Tree[x]);
Tree[x] = temp;
return temp;
}
}
bool visit[MAX];
int maxLevel[MAX];//第i个结点作为根节点时,树的最大深度
int level[MAX];//当前根节点下,第i个结点的层次(深度)
vector<int> graph[MAX];
void dfs(int v,int curRoot){//寻找以curRoot为根节点,从v开始的各个结点的层次
visit[v]=true;
for(int i=0;i<graph[v].size();i++){//遍历每个邻接结点
int k = graph[v][i];//当前邻接结点
if(!visit[k]){
level[k]=level[v]+1;
maxLevel[curRoot]=max(level[k],maxLevel[curRoot]);//跟新最大树深度
dfs(k,curRoot);
}
}
}
int main(void){
int n,a,b;cin>>n;
memset(Tree,-1,sizeof(Tree));
for(int i=1;i<=n-1;i++){
cin>>a>>b;
int na = findRoot(a);
int nb = findRoot(b);
if(na!=nb) Tree[na]=nb;
graph[a].push_back(b);
graph[b].push_back(a);
}
int bCnt=0;//计算连通分支数
for(int i=1;i<=n;i++){
if(Tree[i]==-1) bCnt++;
}
if(bCnt>=2) cout<<"Error: "<<bCnt<<" components"<<endl;
else{
for(int i=1;i<=n;i++){
memset(level,0,sizeof(level));
memset(visit,false,sizeof(visit));
dfs(i,i);//深度优先搜索
}
int deepest = 0;
for(int i=1;i<=n;i++) deepest=max(deepest,maxLevel[i]);
for(int i=1;i<=n;i++){
if(maxLevel[i]==deepest) cout<<i<<endl;
}
}
return 0;
}