题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856
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 (≤10
4
) 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
思路:dfs确定联通分量个数,(完全暴力,因为n=1e4,n^2=1e8,时间给了2s)再每个点dfs找最大高度的点。
其实因为在图联通的情况下,最大高度实际上就是图的两点间最长距离,随便一个点所到达的最远距离一定是最长距离的一部分(可以用反证法证明),所以答案就是先从一个结点dfs后保留最大高度拥有的结点们,然后从这些结点中的其中任意一个开始dfs得到最高高度的结点们,这两个结点集合的并集就是所求。
这里先放最暴力的方法:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 6;
vector <int> g[maxn],ans;
bool vis[maxn];
int dfs(int u) {
vis[u] = 1;
for(int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if(!vis[v]) {
dfs(v);
}
}
}
int solve(int u) {
int res = 1;
vis[u] = 1;
for(int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if(!vis[v]) {
res = max(solve(v) + 1,res);
}
}
return res;
}
int main() {
int n;
ios::sync_with_stdio(0);
cin >> n;
for(int i = 0; i < n-1; i++) {
int u,v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
dfs(i);
cnt++;
}
}
if(cnt > 1) {
cout <<"Error: " << cnt <<" components"<<"\n";
}
else {
int m = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++)vis[j] = 0;
int t = solve(i);
//cout << t << endl;
if(m < t) {
ans.clear();
ans.push_back(i);
//cout << i << endl;
m = t;
}
else if(m == t){
ans.push_back(i);
}
}
for(int i = 0; i < ans.size(); i++) {
cout << ans[i] <<"\n";
}
}
return 0;
}