ABC267 F(树的直径)

题目链接

  题目大意:给我们一棵树求距离\(u\)长度为\(k\)的点是哪一个
  思路:因为直接去找距离为\(k\)的点不太好找,那么需要去固定一条最长的链这样每次查找的时候都尽量在这条链上去找相对应的点,就会把问题变得简单一些,那么树上最长的一条链就应该是这棵树的直径,我们两遍\(dfs\)求出这条链的两个端点,之后查询的时候就只需要让所有的点都往这条链上跳就可以了。

	int n;
	std::cin >> n;
	std::vector<std::vector<int>> adj(n + 1);
	for (int i = 1; i < n; i++) {
		int u, v;
		std::cin >> u >> v;
		adj[u].pb(v);
		adj[v].pb(u);
	}

	int q;
	std::cin >> q;
	std::vector<std::array<int, 2>> event(q);
	std::vector<int> ans(q, -1);
	rep(i,0,q) {
		std::cin >> event[i][0] >> event[i][1];
	}

	std::vector<std::vector<int>> f(n + 1, std::vector<int> (30));
	std::vector<int> dep(n + 1);
	int d1 = 1, d2 = 1;
	std::function<void(int, int)> dfs = [&](int u, int fa) -> void {
		f[u][0] = fa;
		dep[u] = dep[fa] + 1;
		for (int i = 1; i <= 20; i++) {
			f[u][i] = f[f[u][i - 1]][i - 1];
		}
		for (auto& v : adj[u]) {
			if (v == fa) continue;
			dfs(v, u);
		}
	};

	dfs(1, 0);
	rep(i,1,n + 1) d1 = dep[i] > dep[d1] ? i : d1;
	dfs(d1, 0);
	rep(i,1,n + 1) d2 = dep[i] > dep[d2] ? i : d2;

	auto find = [&] (int u, int k) -> int {
		for (int i = 20; ~i; i--) {
			if (k >> i & 1) u = f[u][i];
		}
		return u ? u : -1;
	};

	dfs(d1, 0);
	for (int i = 0; i < q; i++) {
		ans[i] = ans[i] == -1 ? find(event[i][0], event[i][1]) : ans[i];
	}
	dfs(d2, 0);
	for (int i = 0; i < q; i++) {
		ans[i] = ans[i] == -1 ? find(event[i][0], event[i][1]) : ans[i];
	}

	for (auto& x : ans) std::cout << x << "\n"; 


posted @ 2022-09-08 20:41  浅渊  阅读(43)  评论(0)    收藏  举报