多次查询与树上点u距离为k的点,例题
https://atcoder.jp/contests/abc267/tasks/abc267_f
此题目首先有结论:距离树上任意一点距离最远的点,是直径的其中一个端点
https://www.cnblogs.com/ydUESTC/p/16664485.html
故对于一个查询u,k如果存在一个答案,则可以在u到端点L或R的路径中查找到(因为这两条路径已经包含最远路径)
此时,可以离线记录全部查询,然后分别对L和R进行DFS,并记录当前的路径。
当DFS到点u时,对u的全部查询进行处理,对于一个k,答案即为path[sz-1-k]。

#include<bits/stdc++.h> #define fore(x,y,z) for(LL x=(y);x<=(z);x++) #define forn(x,y,z) for(LL x=(y);x<(z);x++) #define rofe(x,y,z) for(LL x=(y);x>=(z);x--) #define all(x) (x).begin(),(x).end() #define fi first #define se second using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; vector<int> adj[200010]; int dis[200010]; int n; int q; int GetFarthest(int u) { memset(dis, 0x3f, sizeof(dis)); dis[u] = 0; queue<int> que; que.push(u); while (que.size()) { int v = que.front(); que.pop(); for (auto nxt : adj[v]) { if (dis[nxt] == 0x3f3f3f3f) { dis[nxt] = dis[v] + 1; que.push(nxt); } } } return max_element(dis + 1, dis + n + 1) - dis; } vector<vector<PII>> query; vector<int> ans; vector<int> path; void DFS(int u,int p) { path.push_back(u); int sz = path.size(); for (auto [k, i] : query[u]) { if (k >= sz) continue; else { if (ans[i] == -1) { ans[i] = path[sz - k - 1]; } } } for (auto nxt : adj[u]) { if (nxt != p) { DFS(nxt, u); } } path.pop_back(); } int main() { cin >> n; fore(i, 1, n - 1) { int a, b; cin >> a >> b; adj[a].push_back(b); adj[b].push_back(a); } int L = GetFarthest(1); int R = GetFarthest(L); cin >> q; query.resize(n + 1); ans.resize(q, -1); fore(i, 0, q - 1) { int u, k; cin >> u >> k; query[u].push_back({ k,i }); } DFS(L,0); DFS(R,0); for (auto res : ans) { cout << res << endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人