1021. Deepest Root (25)
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 (<=10000) 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
结题思路:
题意要求我们找到在以某个节点为Root的情况下,保证树最高,输出全部这样的Root。
要求1:随意抓住一个节点,若有节点掉落,则无需进行的Deepest Root的判断;
要求2:随意抓住一个节点,往下延生最长的那个节点A必定是在Deepest Root的集合中;
若A不在,设A到根节点距离为LA,当前情况下,DR必定不会出现在根节点的与A同子树的子树中,设DR距离跟节点距离为LDR;
此时,抓住DR,往下延长最长的的那个节点B必然会是满足条件的一个根节点,距离原来的根节点为LB;
此时的最深的深度为depth=LDR+LB,然而LB<=LA,所以点A必然可以作为Deepest Root集合当中的一个。
程序步骤:
第一步、并查集判断这是一棵树还是森林;
第二步、随意找一个root,进行深搜,将最深的所有节点保存;
第三步、从保存节中随意选择一个,作为根,进行深搜,将最深的所有节点保存;
第四步、将第二步和第三部中的节点进行合并。
第五步、排序输出即可。
具体程序(AC)如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> node;//并查集使用的数组
vector<bool> deepRootSet;//标记为Deepest Root的集合
vector<int> ResultSet;//保存最后的Deepest Root
vector<int> deep;//保存每个节点的深度
vector<vector<int> > tree;//保存树的二维数组,用于深搜
vector<bool> visited;//节点访问标记符
int depth;//保存树的深度
int getParent(int a)
{
if(node[a]!=a)
return node[a]=getParent(node[a]);
else
return a;
}
void merge(int start,int end)
{
int a=getParent(start);
int b=getParent(end);
if(a>b)
node[a]=b;
else
node[b]=a;
}
int traverseTree(int root,int d)//深搜DFS,返回深度
{
//cout<<root<<endl;
deep[root]=d;
visited[root]=true;
bool flag=false;
int max=-1;
int depthTmp;
for(int i=0;i<tree[root].size();++i)
{
if(!visited[tree[root][i]])
{
flag=true;
depthTmp=traverseTree(tree[root][i],d+1);
if(depthTmp>max)
max=depthTmp;
}
}
if(!flag)
return d;
return max;
}
int main()
{
int n;
cin>>n;
if(n==0)
return 0;
tree.resize(n+5);
visited.resize(n+5,0);
deep.resize(n+5,-1);
deepRootSet.resize(n+5,0);
node.resize(n+5);
for(int i=1;i<=n;++i)
node[i]=i;
int start,end;
for(int i=1;i<n;++i)
{
cin>>start>>end;
tree[start].push_back(end);
tree[end].push_back(start);
merge(start,end);
}
int cons=0;
for(int i=1;i<=n;++i)
if(node[i]==i)
++cons;
if(cons>1)
{
cout<<"Error: "<<cons<<" components"<<endl;
return 0;
}
//森林判断结束
depth=traverseTree(1,0);//深搜过程中保存节点深度,返回最深的深度
int newRoot=1;
for(int i=1;i<=n;++i)
{
if(deep[i]==depth)
{
newRoot=i;
deepRootSet[i]=true;//放入到集合进行标记
}
}
visited.clear();
visited.resize(n+5,0);
depth=traverseTree(newRoot,0);//二次深搜,判断结束
for(int i=1;i<=n;++i)
{
if(deep[i]==depth)
deepRootSet[i]=true;
}
ResultSet.clear();
for(int i=1;i<=n;++i)
if(deepRootSet[i])
ResultSet.push_back(i);
sort(ResultSet.begin(),ResultSet.end());
for(int i=0;i<ResultSet.size();++i)
cout<<ResultSet[i]<<endl;
}