[Codeforces 라운드 # 620 (사업부. 2)] E. 1 나무 및 조회
테스트 당 시간 제한
사초
시험 당 메모리 제한
512메가바이트
입력
표준 입력
산출
표준 출력
길동은 수백만 그루의 나무 걷고, 산 하이킹했다. 그들에 의해 영감을, 그는 갑자기 데이터 구조에서 나무에 대한 흥미로운 아이디어를 내놓았다 : 우리가 나무에 다른 테두리를 추가하면 어떻게?
그리고 그는 그런 나무 같은 그래프라는 것을 발견 한-나무 . 길동이 너무 많은 나무 문제를 해결 지루 이후, 그는 나무에서 유사한 기술이뿐만 아니라 1-나무에 사용할 수 있는지보고 싶었다. 대신 자신이 그것을 해결, 그는 1-나무에 쿼리를 제공하여 테스트하는 것입니다.
첫째, 그는 그는 당신 전분기 대비 쿼리를 요청합니다, 윈 정점 당신에게 나무 (1이 아닌 나무)를 제공합니다. XX, YY, AA, BB, 및 KK : 각 쿼리는 55 개 정수가 포함되어 있습니다. 당신이 정점이 XX와 YY 사이에 양방향 가장자리를 추가 한 후 정확히 KK 가장자리를 포함 BB에 정점 AA에서 경로가 존재하는지 확인하라는 메시지가이 의미합니다. 경로는 동일 정점과 같은 가장자리를 여러 번 포함 할 수 있습니다 . 모든 쿼리는 서로 독립적; 쿼리의 추가 가장자리가 다음 쿼리에서 제거됩니다 즉.
입력
첫 번째 줄은 정수 윈 (3≤n≤1053≤n≤105), 나무의 정점의 수를 포함합니다.
다음에 N-1 N-1 라인과 UU VV (1≤u, v≤n1≤u, v≤n가 유 ≠ VU ≠ v)의 각 정점 및 UU VV 사이의 에지가 의미하는 두 정수를 포함한다. 모든 모서리는 양방향와 구별된다.
다음 줄은 정수 전분기 (1≤q≤1051≤q≤105), 길동 물어보고 싶은 쿼리 수를 포함합니다.
다음 QQ 라인 다섯 개 정수, YY, AA, BB XX를 포함하고, 각 (1≤x, Y, A, b≤n1≤x, Y, A, b≤n, X ≠ YX ≠ Y, 1≤k≤을 KK 1091≤k≤109) - 정수는 설명에 설명했다. XX와 YY 사이의 가장자리가 원래의 트리에 존재하지 않는 것을 보장한다.
산출
정점 XX와 YY 사이의 가장자리를 추가 한 후 BB에 정점 AA에서 정확히 KK 가장자리를 포함하는 경로가 존재하는 경우 각 쿼리의 경우, "YES"인쇄 할 수 있습니다. 그렇지 않으면 "NO"를 인쇄 할 수 있습니다.
당신은 어떤 경우 각 문자 인쇄 (상단 또는 하단) 할 수 있습니다.
예
입력
부
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
산출
부
YES
YES
NO
YES
NO
노트
아래 이미지는 각 쿼리 (점선)의 나무 (원과 실선) 및 추가 가장자리를 설명합니다.
"YES"답변 쿼리의 가능한 경로는 다음과 같습니다
- 11 일 조회 : 11 - 33-22
- 22-ND 쿼리 : 11 - 22-33
- 44 번째 질의 33 - 44 - 22-33 - 44 - 22-33 - 44 - 22-33
질문의 의미 :
노드 N을 포함하는 트리 및 질의 q를 감안할 때.
각 질의는 다섯 개 정수, X, Y, A, B, K 주어진다
대표적인 트리 노드 X 및 Y 에지 노드 사이에 첨가하고, A로부터 B 로의 경로 순수한 여부를 묻는 경우로, 거리 (K) (동일한 노드는 여러 번 이동 수)?
아이디어 :
우리는 최단 경로 길이 a가 b로 긴 경로의 존재를 만족하는 임의의 음이 아닌 정수 (Z)을, L로서 명백 b에 있다고 가정 \ (L + 2 * Z를 \) .
우리가 경로 거리 L 만족이 있는지 여부를 결정해야합니다 그래서 : $ L \ LEQ K $, K와 같은 패리티 L.
그것은 의미 세 개의 경로 (즉, 다른 경로들이 이러한 세 가지 경로를 통해 추가 될 수있다 B, 각 쿼리 A에 대한, 분석에 의해 학습 될 수있다 \ (2 * Z \) )로 정제 :
1 (새롭게 추가 된 에지를 사용하지 않음)에 간단한 경로 B.
2 \ (A-> X-> Y-> B \)
2 \ (A-> Y-> X-> B \)
될 수 패리티 L $ \ $ 당량 K 및 L 및 K : 각각 라인 경로가 있는지를 결정한다.
코드 :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define N maxn
std::vector<int> son[N];
ll depth[N];
int fa[N][21], in[N], a, b;
int n;
int q;
void dfs(int rt, int prev)
{
depth[rt] = depth[prev] + 1;
fa[rt][0] = prev;
for (int i = 1; i < 20; i++)
{
fa[rt][i] = fa[fa[rt][i - 1]][i - 1];
}
for (int i = 0; i < son[rt].size(); i++)
{
if (son[rt][i] == prev)
continue;
dfs(son[rt][i], rt);
}
}
int LCA(int x, int y)
{
if (depth[x] < depth[y])
swap(x, y);
for (int i = 19; i >= 0; i--)
{
if (depth[x] - (1 << i) >= depth[y])
{
x = fa[x][i];
}
}
if (x == y)
{
return x;
}
for (int i = 19; i >= 0; i--)
{
if (fa[x][i] != fa[y][i])
{
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
ll dist(int a, int b)
{
int u = LCA(a, b);
ll L = depth[a] + depth[b] - 2ll * depth[u];
return L;
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
depth[0] = -1;
n = readint();
repd(i, 2, n)
{
a = readint();
b = readint();
son[a].push_back(b);
son[b].push_back(a);
}
dfs(1, 0);
q = readint();
int x, y;
ll k;
while (q--)
{
x = readint();
y = readint();
a = readint();
b = readint();
k = readll();
ll disab = dist(a, b);
ll disaxyb = dist(a, x) + 1 + dist(y, b);
ll disayxb = dist(a, y) + 1 + dist(x, b);
int isok = 0;
ll ans = inf;
if (disab % 2 == k % 2)
{
ans = min(ans, disab);
}
if (disaxyb % 2 == k % 2)
{
ans = min(ans, disaxyb);
}
if (disayxb % 2 == k % 2)
{
ans = min(ans, disayxb);
}
if (ans <= k)
{
isok = 1;
}
if (isok)
{
printf("YES\n");
} else
{
printf("NO\n");
}
}
return 0;
}