struct Tree {int n, d = 0; //顶点,直径,树中心//自顶向下u到其叶子结点最远距离d1,次长距离d2(与最长路径无公共边)//p1,p2表示结点u向下更新时是由哪个结点更新来的//up表示结点u向上到祖宗结点的最远距离vector<int> d1, d2, p1, p2, up;vector<vector<int>> g;Tree(int n): n(n), d1(n + 1), d2(n + 1), g(n + 1), p1(n + 1), p2(n + 1), up(n + 1) {}void add(int u, int v) {g[u].emplace_back(v);g[v].emplace_back(u);}//求直径//自顶向下求u到叶子结点的最远距离void dfs(int u, int fa) {d1[u] = d2[u] = 0;for (auto v : g[u]) {if (v == fa)continue;dfs(v, u);auto t = d1[v] + 1;if (t > d1[u]) {d2[u] = d1[u], p2[u] = p1[u];d1[u] = t, p1[u] = v;} else if (t > d2[u]) {d2[u] = t, p2[u] = v;}}d = max(d, d1[u] + d2[u]);}//自底向上求u到其它结点的最长路径void dfsup(int u, int fa) {for (auto v : g[u]) {if (v == fa) continue;//如果父结点u向下的最长路径经过vif (p1[u] == v) {//结点v向上走到最长路径为//父结点u继续向上的的最长路径和u向下走的次长路径的最大值+边权up[v] = max(up[u], d2[u]) + 1;} else {//如果父结点u向下的最长路径不经过vup[v] = max(up[u], d1[u]) + 1;}dfsup(v, u);}}//求树的直径int FindDiameter() {dfs(1, 0);return d;}//求树的中心vector<int> FindCenter() {dfsup(1, 0);i64 res = INT_MAX;vector<int> mid;for (int i = 1; i <= n; i ++) {auto t = max(d1[i], up[i]);if (t < res) {res = t;vector<int>().swap(mid);mid.emplace_back(i);} else if (t == res) {mid.emplace_back(i);}}return mid;}};