多次查询与树上点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; }View Code
标签:nxt,例题,int,DFS,查询,que,path,树上,dis 来源: https://www.cnblogs.com/ydUESTC/p/16664728.html