题目:http://codeforces.com/contest/1304/problem/E
参考:https://www.cnblogs.com/CADCADCAD/p/12321407.html
题意:给定一棵树,多次询问,每次询问,再添加了x到y的边后,从a到b是否有一长度为k的路径,这里路径允许重复经过点和树边。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n;
struct edge{
int v,nxt;
}e[maxn<<1];
int tot,head[maxn];
void addedge(int u,int v) {
e[tot].v = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
void init() {
tot = 0;
memset(head,-1,sizeof(head));
}
int dep[maxn],sz[maxn],son[maxn],f[maxn];
int top[maxn];
void dfs1(int u,int fa,int deep) {
dep[u] = deep,f[u] = fa,sz[u] = 1;
int mxson = -1;
for(int i = head[u];~i;i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
dfs1(v,u,deep+1);
sz[u] += sz[v];
if(sz[v] > mxson) mxson = sz[v],son[u] = v;
}
}
void dfs2(int u,int fr) {
top[u] = fr;
if(son[u]) dfs2(son[u],fr);
for(int i = head[u];~i;i = e[i].nxt) {
int v = e[i].v;
if(v == son[u] || v == f[u]) continue;
dfs2(v,v);
}
}
int dis(int x,int y) {
int ans = dep[x]+dep[y];
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
ans -= 2*dep[x];
return ans;
}
bool Check(int &d,int &k) {
return d <= k && (d%2 == k%2);
}
int main() {
scanf("%d",&n);
init();
for(int i = 1,u,v;i < n;i++) {
scanf("%d%d",&u,&v);
addedge(u,v);addedge(v,u);
}
dfs1(1,1,0);dfs2(1,1);
int q;scanf("%d",&q);
while(q--) {
int x,y,a,b,k;
scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
bool ok = 0;
int ab = dis(a,b);
int ax = dis(a,x),ay = dis(a,y);
int bx = dis(b,x),by = dis(b,y);
int d1 = ax+by+1,d2 = ay+bx+1;
if(Check(ab,k) || Check(d1,k) || Check(d2,k))
puts("YES");
else
puts("NO");
}
return 0;
}