CF1304E 1-Trees and Queries
对树的路径进行操作,不难想到树的路径是唯一的,离不开LCA
添加一条新边后,答案有两种可能,一是走原树上路径,二是通过这条边走到
对于后者,其实答案就是dis(a,x)+1+dis(y,b)或者dis(a,y)+1+dis(x,b)
均是树上原有的,LCA可求
但是有个特殊情况,可以反复横跳(恶心心
但是反复横跳的奇偶性不变,只要有一个答案<=K并且和K奇偶性相同即可
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 100005
struct edge {
int v,next;
} G[MAXN<<1];
int head[MAXN],tot = 0;
inline void add(int u,int v) {
G[++tot].v = v; G[tot].next = head[u]; head[u] = tot;
}
struct Tree {
int son[MAXN],size[MAXN],fa[MAXN],d[MAXN];
int top[MAXN];
void dfs1(int u,int father) {
fa[u] = father; d[u] = d[father] + 1;
size[u] = 1; son[u] = 0;
for(int i=head[u];i;i=G[i].next) {
int v = G[i].v; if(v==fa[u]) continue;
dfs1(v,u); size[u] += size[v];
if(size[v]>size[son[u]]) son[u] = v;
}
}
void dfs2(int u,int tp) {
top[u] = tp;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=G[i].next) {
int v = G[i].v; if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
inline void init() {
d[1] = size[0] = 0;
dfs1(1,1); dfs2(1,1);
}
inline int LCA(int u,int v) {
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]]) swap(u,v);
u = fa[top[u]];
}
return d[u]>d[v]?v:u;
}
inline int dis(int u,int v) {
int lca = LCA(u,v);
return (d[u]-d[lca]) + (d[v]-d[lca]);
}
} tr;
inline bool check(int dis1,int dis2) {
return (dis1<=dis2&&(dis1&1)==(dis2&1));
}
int N,Q;
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N;
for(int i=1;i<N;++i) {
int u,v; cin >> u >> v;
add(u,v); add(v,u);
}
tr.init();
cin >> Q;
for(int i=1;i<=Q;++i) {
int x,y,a,b,k; cin >> x >> y >> a >> b >> k;
if(check(tr.dis(a,b),k)||check(tr.dis(a,x)+1+tr.dis(y,b),k)||check(tr.dis(a,y)+1+tr.dis(x,b),k)) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}