https://ac.nowcoder.com/acm/contest/5902/C
感谢LDK大神提供的最后解法
一个点z 到另一个点集合S的最长路为 ans
集合S中的最远点对x,y
ans = max(ans,dis(x,z),dis(y,z));
就是这样了
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<unordered_map> using namespace std; typedef long long ll; const int maxn = 2e5 + 7; vector<int>G[maxn], ins[maxn]; unordered_map<int, int >id; int n; void add(int x, int y) { G[x].push_back(y); } int dep[maxn], top[maxn], fa[maxn], siz[maxn]; int cns[maxn]; int son[maxn]; int dfs1(int x, int f, int d) { dep[x] = d; fa[x] = f; siz[x] = 1; int s = 0; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == f) continue; dfs1(p, x, d + 1); siz[x] += siz[p]; if (s < siz[p]) { s = siz[p]; son[x] = p; } } return 0; }//haah int cnt = 0; int dfs2(int x, int t) { top[x] = t; if (!son[x]) return 0; dfs2(son[x], t);//重儿子重复利用t for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa[x] || p == son[x]) continue; dfs2(p, p);//轻儿子新建t } return 0; } int LCA(int u, int v) { while (top[u] != top[v])//u、v不在同一条重链上时 { if (dep[top[u]] > dep[top[v]])//将深度大的上提 u = fa[top[u]]; else v = fa[top[v]]; } if (dep[u] < dep[v])//返回u、v中在较上方的那个 return u; return v; } int get(int x, int y) {//点之间的距离 int root = LCA(x, y); return dep[x] + dep[y] - 2 * dep[root]; } int main() { //******准备*********// int q; scanf("%d %d", &n, &q); int x; int c = 0; for (int i = 1; i <= n ; i++) { scanf("%d", &x); cns[i] = x; if (id[x] == 0) id[x] = ++c; ins[id[x]].push_back(i); } for (int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } dfs1(1, -1, 0); dfs2(1, 1); //******开始********// for (int i = 1; i <= n; i++) { if (ins[i].size() < 2) continue; int s = ins[i][0]; int t = ins[i][1]; int ln = get(s, t); for (int j = 2; j < ins[i].size(); j++) { int x = ins[i][j]; int a = get(x, s); int b = get(x, t); if (a > b) { if (a > ln) { ln = a; t = x; } } else { if (b > ln) { ln = b; s = x; } } } ins[i].clear(); ins[i].push_back(s); ins[i].push_back(t); } while (q--) { int x, y; int ans = 0; scanf("%d%d", &x, &y); x = id[x]; y = id[y]; if (ins[x].size() == 0 || ins[y].size() == 0) { printf("0 "); } else { for (int i = 0; i < ins[x].size(); i++) { for (int j = 0; j < ins[y].size(); j++) { int s = ins[x][i]; int t = ins[y][j]; ans = max(get(s, t), ans); } } printf("%d ", ans); } } return 0; }