[Codeforces 라운드 # 620 (사업부. 2)] E. 1 나무 및 검색어 (트리 LCA 패리티)

[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

노트

아래 이미지는 각 쿼리 (점선)의 나무 (원과 실선) 및 추가 가장자리를 설명합니다.

IMG

"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;
}


추천

출처www.cnblogs.com/qieqiemin/p/12323832.html