When I was doing a synchronization competition, I thought it was wrong. The status was always good or bad. This was the final result for the semi-finals.

For a tree, let's find two points on the tree, so that the distance between the other points and the two points is the smallest.

After the game, I used the O (n) algorithm. In fact, this question is not difficult. Not ..

In fact, these two points must be the two points on the tree diameter. If you can think of them, you just need to find the diameter of the tree and then split the tree into two Subtrees from the middle, then we can find the center of the subtree separately.

The proof is as follows. If we have obtained two vertices on the tree, U and V meet the conditions. So, it is certainly optimal for us to split the tree from the center of U and V, which is easy to think. Then, for the U point, it must be in the diameter of the original tree, because if the U point is not in the diameter, the U point must be in a branch of the subtree, in addition, the distance to the tree diameter endpoint is less than or equal to the distance from u to the branch endpoint. In this way, the branch can replace an endpoint on the original diameter to become the diameter, and the U is in the diameter, conflicts with assumptions. So u must be in the diameter, and V must be in the diameter. Then we came up with =

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<vector>#include<string>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define LL long long#define INF 0x3f3f3f3f#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 202000;vector<int> G[maxn];vector<int> d;bool vis[maxn];int fa[maxn];int bfs1(int s){int ret = -1;CLR(vis, false);vis[s] = true;queue<int> q; fa[s] = -1;q.push(s); vis[s] = true;while(!q.empty()){int u = q.front(); q.pop();ret = u;for(int i = 0; i < G[u].size(); i ++){int v = G[u][i];if(vis[v]) continue;vis[v] = true;q.push(v); fa[v] = u;}}return ret;}int deg[maxn];int cnt[maxn], n;pair<int, int> bfs2(int u, int fa){queue<int> q;CLR(vis, false);q.push(u);vis[u] = true;if(deg[u] == 0) return make_pair(u, 0);while(!q.empty()){int u = q.front(); q.pop();for(int i = 0; i < G[u].size(); i ++){int v = G[u][i];if(vis[v] || v == fa) continue;q.push(v); vis[v] = true;}}queue<pair<int, int> > q2;for(int i = 1; i <= n; i ++)if(vis[i]){if(deg[i] == 1) q2.push(make_pair(i, 0));else vis[i] = false;}pair<int, int> ret;CLR(cnt, 0);while(!q2.empty()){pair<int, int> u = q2.front(); q2.pop();ret = u;cnt[u.second] ++;for(int i = 0; i < G[u.first].size(); i ++){int v = G[u.first][i], len = u.second + 1;if(v == fa || deg[v] == 1) continue;deg[v] --;if(deg[v] == 1) q2.push(make_pair(v, len));}}if(cnt[ret.second] > 1) ret.second ++;return ret;}inline int get_int(){int ret=0;char c;while(!isdigit(c=getchar()));do {ret = (ret<<3)+(ret<<1)+c-'0';}while(isdigit(c=getchar()));return ret;}int main(){int T;scanf("%d", &T);while(T --){scanf("%d", &n);for(int i = 1; i <= n; i ++)G[i].clear(), deg[i] = 0;for(int i = 1; i < n; i ++){int u = get_int(), v = get_int();G[u].push_back(v);G[v].push_back(u);deg[u] ++; deg[v] ++;}d.clear();int s =bfs1(bfs1(1));for(int i = s; ~i; i = fa[i]){d.push_back(i);}int u = d[d.size() / 2], v = d[d.size() / 2 - 1];deg[u] --; deg[v] --;pair<int, int> r1 = bfs2(u, v), r2 = bfs2(v, u);int ans = max(r1.second, r2.second);printf("%d %d %d\n", ans, r1.first, r2.first);}}/*22241 21 31 451 22 33 44 5111 22 33 44 55 66 77 86 99 1010 11*/

Zoj 3820 building fire stations)