Loading

CodeForces-1304E 1-Trees and Queries

1-Trees and Queries

LCA 倍增 + 思维

因为这里的路径不是简单路径,因此只要符合最短路径长度 不大于 \(k\),且最短路径长度与 \(k\) 的奇偶性相同,就必定有路径可以到(反复走一步,退一步)

加入一条边之后,可能会产生另一条路径的奇偶性与最短路径的奇偶性不同,因此我们考虑检测三种路径与 \(k\) 的关系(大小 与 奇偶性)

  1. 考虑从 \(a\)\(b\) 的最短路径

  2. 考虑 \(a->x\), \(x->y\), \(y->b\) 的最短路径

  3. 考虑 \(a->y\), \(y->x\), \(x->b\) 的最短路径

路径长度计算直接用倍增求 \(LCA\)\(dep\) 计算距离即可

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5 + 10;
vector<int>gra[maxn];
int dep[maxn], fa[maxn][20];

void dfs(int now, int pre, int d)
{
    fa[now][0] = pre;
    dep[now] = d;
    for(int nex : gra[now])
    {
        if(nex == pre) continue;
        dfs(nex, now, d + 1);
    }
}

void init(int n)
{
    dfs(1, 1, 1);
    for(int i=1; i<20; i++)
        for(int j=1; j<=n; j++)
            fa[j][i] = fa[fa[j][i-1]][i-1];
}

int LCA(int u, int v)
{
    if(dep[u] < dep[v]) swap(u, v);
    int dif = dep[u] - dep[v];
    for(int i=19; i>=0; i--)
    {
        if(dif >= (1 << i))
        {
            dif -= 1 << i;
            u = fa[u][i];
        }
    }
    if(u == v) return u;
    for(int i=19; i>=0; i--)
    {
        if(fa[u][i] != fa[v][i])
        {
            u = fa[u][i];
            v = fa[v][i];
        }
    }
    return fa[u][0];
}

int dis(int u, int v)
{
    int lca = LCA(u, v);
    return dep[u] - dep[lca] * 2 + dep[v];
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i=1; i<n; i++)
    {
        int a, b;
        cin >> a >> b;
        gra[a].push_back(b);
        gra[b].push_back(a);
    }
    init(n);
    int q;
    cin >> q;
    while(q--)
    {
        int x, y, a, b, k;
        cin >> x >> y >> a >> b >> k;
        int disa = dis(a, b);
        int disb = dis(a, x) + dis(b, y) + 1;
        int disc = dis(a, y) + dis(x, b) + 1;
        int f = 0;
        if(disa <= k && (k - disa) % 2 == 0) f = 1;
        else if(disb <= k && (k - disb) % 2 == 0) f = 1;
        else if(disc <= k && (k - disc) % 2 == 0) f = 1;
        if(f) cout << "YES\n";
        else cout << "NO\n";
    }
    cout << endl;
    return 0;
}
posted @ 2022-07-29 15:44  dgsvygd  阅读(32)  评论(0)    收藏  举报