PAT甲级 1021 Deepest Root
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 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
这道题一开始没啥思路,想暴力然后T了,后来看了图论的知识懂了,要找符合条件的根节点:
1.在树上任取一点
,
得到最深结点集合
2.在从集合
任取一点
,
得到最深结点集合
3.答案即为
:注意特判
的情况
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+5;
vector<int>G[N];
set<int>s;//A∪B,选set可以去重且自动排序
int n,u,v,cnt;
int deep[N],vis[N];
int ans=0,maxdeep=1;
void dfs(int u){
vis[u]=1;
for(int v:G[u]){
if(!vis[v]){
deep[v]=deep[u]+1;
maxdeep=max(maxdeep,deep[v]);
dfs(v);
}
}
}
int main() {
scanf("%d",&n);
for(int i=0;i<n-1;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
cnt=0;
memset(vis,0,sizeof(vis));
deep[1]=1;maxdeep=0;
int p;//记录A中任一最深结点
for(int i=1;i<=n;i++){
if(!vis[i]) {dfs(i);cnt++;}//第一遍DFS得到联通块的数量
if(deep[i]==maxdeep){
s.insert(i);p=i;//集合A
}
}
memset(vis,0,sizeof(vis));
deep[p]=1;maxdeep=0;
dfs(p);
for(int i=1;i<=n;i++){
if(deep[i]==maxdeep){
s.insert(i);//集合B
}
}
if(n==1) puts("1");
else if(cnt>1){
printf("Error: %d components",cnt);
}
else{
for(set<int>::iterator i=s.begin();i!=s.end();i++)
printf("%d\n",*i);
}
return 0;
}