Problem Description:
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 N N ( ≤ 1 0 4 \leq 10^4 ≤104) which is the number of nodes, and hence the nodes are numbered from 1 to N N N. Then N − 1 N−1 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
Problem Analysis:
数据范围为 1 ≤ N ≤ 1 0 4 1\leq N\leq 10^4 1≤N≤104,并且时限为 2s,因此可以考虑使用暴力枚举每一个节点作为根,然后进行树的遍历,并不断更新最深的高度。开一个存储最深根节点的数组,如果后续节点的高度与当前更新到的最深高度相等,就将这个节点假如数组中;若出现了更高的高度,就将数组清空,重新累计。
这里可以使用 BFS 或者 DFS 来遍历整颗树,理论上来说两种方案,对于每一个根的遍历,每个节点都只会访问一次,因此都是 O ( n 2 ) O(n^2) O(n2) 的。但 AcWing 上数据过强,最后一个点卡掉了我的 BFS 做法。
Code
BFS
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 10010, M = N * 2;
int n, maxh;
int p[N];
int h[N], e[M], ne[M], idx;
int q[N], dist[N];
bool st[N];
vector<int> ans;
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void bfs(int root)
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
int hh = 0, tt = -1;
dist[root] = 0;
st[root] = true;
q[ ++ tt] = root;
int maxtmp = -1;
while (hh <= tt)
{
auto t = q[hh ++ ];
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + 1)
{
dist[j] = dist[t] + 1;
if (dist[j] > maxtmp) maxtmp = dist[j];
if (!st[j])
{
st[j] = true;
q[ ++ tt] = j;
}
}
}
}
if (maxtmp > maxh)
{
maxh = maxtmp;
ans.clear();
ans.push_back(root);
}
else if (maxtmp == maxh) ans.push_back(root);
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化并查集
for (int i = 0; i < n - 1; i ++ ) // 建图,只有n-1条边
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
if (find(a) != find(b)) p[find(a)] = find(b);
}
int comp = 0; // 找到每个连通分量的代表元素,累计代表元素数量,如果为1,说明是树,否则是图
for (int i = 1; i <= n; i ++ )
if (p[i] == i)
comp ++ ;
if (comp > 1) printf("Error: %d components\n", comp);
else
{
maxh = -1;
for (int i = 1; i <= n; i ++ ) // 以每个点都作为一个根进行 BFS
bfs(i);
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i ++ )
cout << ans[i] << endl;
}
return 0;
}
DFS
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 10010, M = N * 2;
int n, maxh;
int p[N];
int h[N], e[M], ne[M], idx;
vector<int> ans;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int dfs(int u, int father) // 返回从 当前节点往下搜,最高的高度为多少
{
int depth = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == father) continue;
depth = max(depth, dfs(j, u) + 1);
}
return depth;
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ ) p[i] = i;
for (int i = 0; i < n - 1; i ++ )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
if (find(a) != find(b)) p[find(a)] = find(b);
}
int comp = 0;
for (int i = 1; i <= n; i ++ )
if (p[i] == i)
comp ++ ;
if (comp > 1) printf("Error: %d components\n", comp);
else
{
maxh = -1;
for (int i = 1; i <= n; i ++ )
{
int depth = dfs(i, -1);
if (depth > maxh)
{
maxh = depth;
ans.clear();
ans.push_back(i);
}
else if (depth == maxh) ans.push_back(i);
}
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i ++ )
cout << ans[i] << endl;
}
return 0;
}