1021 Deepest Root (25 分)
A graph which is connecte d and acyclic can be considered a tree. The hight 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
这题大概意思是说给我们N个点,从0-N编号,然后再给我们N-1条边,连接这N个点,若能构成树,求能构成的树深度最大的树的根节点,若无法构成树则输出可分成几个连通分量。
思路如下:先求连通分量,求连通分量无非就是求对这个图进行深度搜索的时候一共调用了几次深度优先搜索函数,如果图是连通的则调用一次深度优先搜索函数就可完成对图的搜索,若不是连通图则需调用多次,调用的次数即为连通分量数。若调用了多次则直接输出 Error : K components,再结束程序即可,若只调用一次则说明为连通图,我们还需要求得深度最大的树的根节点。
首先我先在这说明一个结论,即为从图中任意一个结点开始深度搜索,将高度最高的一个或几个结点记录下来,再从这几个结点中的任意一个结点开始深度搜索,再把高度最大的一个或几个结点记录下来,对这两个结点的集合求并集即为我们所求的深度最大的树的根节点。
因此在这里需要对深度优先搜索算法做一点修改,以符合我们的需要。因此我建了一个整型vector用以存放在第一次深度搜索中高度最大的一个或几个结点。然后取出这个vector中保存的任意一个结点从这个结点开始再进行一次DFS,同样,把这次深度搜索得到的高度最高的结点也放入vector,对这两个结果的集合求并集,再排序,即为我们需要的答案。
代码如下,供参考:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> farthestNode;
int maxHeight = 0;
void DFS(vector<bool> &visit, vector<int> &farthestNode, vector<vector<bool>> &E, int index, int height)
{
if (height > maxHeight) //保留一次搜索最大的一个结点
{
farthestNode.clear();
farthestNode.push_back(index);
maxHeight = height;
}
else if (maxHeight == height) //一样大的那个也保留
{
farthestNode.push_back(index);
}
visit[index] = true;
for (int i = 1; i <= visit.size() - 1; i++)
{
if (visit[i] == false && E[index][i] == true)
{
DFS(visit, farthestNode, E, i, height + 1);
}
}
}
int main()
{
int N;
cin >> N;
vector<bool> visit(N + 1);
vector<vector<bool>> E(N + 1);
for (int i = 1; i <= N; i++)
{
E[i].resize(N + 1);
}
for (int i = 0; i < N - 1; i++)
{
int a, b;
cin >> a >> b;
E[a][b] = E[b][a] = true;
}
int CC = 0;
int height = 1;
for (int i = 1; i <= N; i++)
{
if (visit[i] == false)
{
DFS(visit, farthestNode, E, i, height);
CC++;
}
}
if (CC > 1)
{
cout << "Error: "<<CC<<" components";
}
else if (CC == 1)
{
int k = farthestNode[0];
vector<int> save;
for (int i = 0; i <= N; i++)
{
visit[i] = false;
}
height = 1;
maxHeight = 0;
DFS(visit, save, E, k, height);
for (int i = 0; i < save.size(); i++)
{
farthestNode.push_back(save[i]);
}
sort(farthestNode.begin(), farthestNode.end()); //必须先排序
farthestNode.erase(unique(farthestNode.begin(), farthestNode.end()), farthestNode.end()); //去重
for (int i = 0; i < farthestNode.size(); i++)
{
cout << farthestNode[i] << endl;
}
}
return 0;
}
对比了一下柳神的代码,在时间复杂度和空间复杂度上简直是吊打我啊,在此放出我们测试结果和柳神的测试结果。
这是我的:
这是柳神的:
水平还差很远,不过这才是oj的魅力,如果各位对时间复杂度和空间复杂度的优化有想法的可以在下面评论,在下菜鸟,请轻喷。