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
题目大意:给出n个结点(1~n)之间的n条边,问是否能构成一棵树,如果不能构成则输出它有的连通分量个数,如果能构成一棵树,输出能构成最深的树的高度时,树的根结点。如果有多个,按照从小到大输出。
分析:首先深度优先搜索判断它有几个连通分量。如果有多个,那就输出Error: x components,如果只有一个,就两次深度优先搜索,先从一个结点dfs后保留最高高度拥有的结点们,然后从这些结点中的其中任意一个开始dfs得到最高高度的结点们,这两个结点集合的并集就是所求
解法一:此方法用vector<vector<int> edge来存储边,避免了内存不超过
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<set>
using namespace std;
const int maxsize = 10001;
int n,e;
bool visited[maxsize];
vector<vector<int>> edge;
int maxheight=-1;
vector<int> temp;
set<int> myset;
void dfs(int v,int height){
if(height>maxheight){
maxheight = height;
temp.clear();
temp.push_back(v);
}else if(height == maxheight){
temp.push_back(v);
}
visited[v] = 1;
for(int i=0;i<edge[v].size();i++){//注意,这里是通过下标,所以是从0开始
if(visited[edge[v][i]]==0){
dfs(edge[v][i],height+1);
}
}
}
int main(){
memset(visited,0,sizeof(visited));
cin>>n;
edge.resize(n+1);
e = n-1;
for(int i=1;i<=e;i++)
{
int a,b;
cin>>a>>b;
edge[a].push_back(b);//通过下标读取一个vector
edge[b].push_back(a);
}
int cnt = 0;
for(int i=1;i<=n;i++){
if(!visited[i]){
cnt++;
dfs(i,1);
}
}
if(cnt>=2){
cout<<"Error: "<<cnt<<" components";
return 0;
}
for(auto it:temp){//先把最深的点加进来,再以这其中的一个顶点再进行一次DFS
myset.insert(it);
}
memset(visited,0,sizeof(visited));
int node = temp[0];
temp.clear();
dfs(node,1);
for(auto it:temp){
myset.insert(it);
}
for(auto it:myset){
cout<<it<<endl;
}
return 0;
}
解法二:通过常规二维矩阵来存储edge
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<set>
using namespace std;
const int maxsize = 10001;
int n,e;
bool visited[maxsize];
int edge[maxsize][maxsize];
int maxheight=-1;
vector<int> temp;
set<int> myset;
void dfs(int v,int height){
visited[v] = 1;
if(height>maxheight){
maxheight = height;
temp.clear();//先清空
temp.push_back(v);
}else if(height == maxheight){
temp.push_back(v);
}
for(int i=1;i<=n;i++){
if(edge[v][i]==1 && visited[i]==0){
dfs(i,height+1);
}
}
}
int main(){
memset(visited,0,sizeof(visited));
cin>>n;
e = n-1;
for(int i=1;i<=e;i++)
{
int a,b;
cin>>a>>b;
edge[a][b] = edge[b][a] = 1;
}
int cnt = 0;
for(int i=1;i<=n;i++){
if(!visited[i]){
cnt++;
dfs(i,1);
}
}
if(cnt>=2){
cout<<"Error: "<<cnt<<" components";
return 0;
}
for(auto it:temp){//先把最深的点加进来,再以这其中的一个顶点再进行一次DFS
myset.insert(it);
}
int node = temp[0];
temp.clear();//重新dfs前要清空
memset(visited,0,sizeof(visited));//再次置0
dfs(node,1);//选择第一次dfs中任意一个最深的结点作为第二次dfs起点即可
for(auto it:temp){
myset.insert(it);
}
for(auto it:myset){
cout<<it<<endl;
}
return 0;
}