牛客网 漂亮的树

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;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/13033656.html