CF-div2-620-E. 1-Trees and Queries LCA 树上点距离
Posted fisherss
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF-div2-620-E. 1-Trees and Queries LCA 树上点距离相关的知识,希望对你有一定的参考价值。
思路
树链剖分求出LCA
用LCA求两点之间距离(借助到根的距离):depth[x] + depth[y] - 2*depth[LCA];
加边后a,b两点可以保持距离为k的条件: k>=改变后的距离; 改变后的距离刚好等于k,如果不等那么距离相差偶数,来回走来走去就能走到走凑成k
考虑加边对a,b距离的影响;有三种情况
1.加边后,不影响a,b
2.a先到x,x再走到y(这里新加的边,距离为1),y再走到b
3.a先到y,y再走到x(+1),x再走到b
判断最终距离<=k,并且相差为偶数
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+100;
vector<int> g[maxn];
ll fa[maxn],depth[maxn],sz[maxn],son[maxn],id[maxn],rk[maxn],top[maxn],bot[maxn];
int cnt = 0;
int n,q,root = 1;
/*
树链剖分求LCA
LCA求两点之间距离(借助到根的距离):depth[x] + depth[y] - 2*depth[LCA];
可以保持距离为k的条件: k>=改变后的距离; 改变后的距离刚好等于k,如果不等那么距离相差偶数,来回走来走去就能走到走凑成k
*/
void dfs(int x,int deep){
depth[x] = deep;
sz[x] = 1;
for(int li = 0;li<g[x].size();li++){
int i = g[x][li];
if(i == fa[x]) continue;
fa[i] = x;
dfs(i,deep+1);
sz[x] += sz[i];
if(sz[i] > sz[son[x]]) son[x] = i;
}
}
void dfs2(int x,int tp){
top[x] = tp;
id[x] = ++cnt;
rk[cnt] = x;
if(son[x]) dfs2(son[x],tp),bot[x] = bot[son[x]];
else bot[x] = x;
for(int li=0;li<g[x].size();li++){
int i = g[x][li];
if(i != fa[x] && i != son[x])
dfs2(i,i);
}
}
int lca(int u,int v){
while(top[u] != top[v]){
if(depth[top[u]] < depth[top[v]]) swap(u,v);
u = fa[top[u]];
}
if(depth[u] < depth[v]) return u;
return v;
}
//求两点之间的简单路径距离
ll dis(int x,int y){
int LCA = lca(x,y);
return depth[x] + depth[y] - 2*depth[LCA];
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n-1;i++){
ll u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(root,1);
dfs2(root,root);
cin>>q;
while(q--){
ll x,y,a,b,k;
cin>>x>>y>>a>>b>>k;
ll ans = 0x3f3f3f3f;
//a,b两点与x,y有三种关系
ll dist1 = dis(a,b); //无关
ll dist2 = dis(a,x) + dis(y,b) + 1; //a先到x,x再走到y(这里新加的边,距离为1),y再走到b
ll dist3 = dis(a,y) + dis(x,b) + 1;
bool flag = false;
if((k - dist1)%2 == 0 && dist1 < ans) ans = dist1;
if((k - dist2)%2 == 0 && dist2 < ans) ans = dist2;
if((k - dist3)%2 == 0 && dist3 < ans) ans = dist3;
if(ans <= k) flag = true;
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
/*
5
1 2
2 3
3 4
4 5
5
1 3 1 2 2
1 4 1 3 2
1 4 1 3 3
4 2 3 3 9
5 2 3 3 9
*/
以上是关于CF-div2-620-E. 1-Trees and Queries LCA 树上点距离的主要内容,如果未能解决你的问题,请参考以下文章
CF-div3-635-E - Three Blocks Palindrome| 二分
CF-Div2-832 D. Yet Another Problem(bitmask&结论)
CF-Div2-832 D. Yet Another Problem(bitmask&结论)
CF-div3-611-F. DIY Garland 优先队列 构造树