CodeFroce #620 E 1-Trees ans Queries (LCA)

题目地址:http://codeforces.com/contest/1304/problem/E

LCA不怎么会就写个题解理理清楚吧

题意:给你n个结点树,之后有q个询问,每个询问给出x,y,a,b,k五个整数,问在x,y之间添加一条边的情况下,能否从a走恰好k步到达b点。(可重复经过边与点)

首先以1为起点用 倍增+dfs 求LCA。这样就方便快速计算这棵树上任意两点间的距离。之后计算a,b之间的距离,以及a经过x,y之间的捷径到b的最小距离(如果不走捷径,就相当于直接a到b了)。距离的奇偶性与k相同才能算入答案,之后答案最小值与k比较,<=k时成立

//LCA初始化
void build(int cur, int p)//cur为当前节点,p为cur的父节点
{
    dep[cur] = dep[p] + 1;//深度为父节点+1
    par[cur][0] = p; //表示cur向上走2^0步到达的节点
    for(int i = 1;i <= 17;i++)par[cur][i] = par[par[cur][i - 1]][i - 1];//向上2^(i - 1) * 2 个结点
    
    for(auto it : vv[cur])
    {
        if(it != p) build(it, cur);//继续向下递归
    }
}
//求a,b两节点在树上的距离
int lca_len(int a, int b)
{
    int len = 0;

    //将a,b变为深度相等
    if(dep[a] > dep[b]) swap(a, b);
    for (int i = 17; i >= 0;i--)
    {
        if(dep[par[b][i]] >= dep[a])
        {
            b = par[b][i];
            len += (1 << i);
        }
    }

    
    if(a == b) return len;//如果a为b的祖先,就不用后面返回len+2了
    for (int i = 17; i >= 0;i--)
    {
        if(par[a][i] != par[b][i])
        {
            a = par[a][i];
            b = par[b][i];
            len += (1 << (i + 1));//两点同时向上走2^i步,所以*2
        }
    }
    return len + 2;
}
//题目代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e5 + 7;
const ll INF = 1e9 + 10;
int n, q;
int x, y, a, b;
ll k;

vector<int> vv[N];
int dep[N], par[N][18];
//lca 首先使用


void build(int cur, int p)
{
    dep[cur] = dep[p] + 1;
    par[cur][0] = p;
    for (int i = 1; i <= 17;i++) par[cur][i] = par[par[cur][i - 1]][i - 1];

    for(auto it : vv[cur])
    {
        if(it != p) build(it, cur);
    }
}


int lca_len(int x, int y)
{
    if(dep[x] > dep[y]) swap(x, y);
    int len = 0;
    for (int i = 17; i >= 0;i--)
    {
        if(dep[par[y][i]] >= dep[x])
        {
            y = par[y][i];
            len += (1 << i);
        }
    }


    if(x == y) return len;

    for (int i = 17; i >= 0;i--)
    {
        if(par[y][i] != par[x][i])
        {
            x = par[x][i];
            y = par[y][i];
            len += (1 << (i + 1));
        }
    }
    return len + 2;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i < n;i++)
    {
        scanf("%d %d", &x, &y);
        vv[x].push_back(y);
        vv[y].push_back(x);
    }
    build(1, 0);
    scanf("%d", &q);
    while(q--)
    {
        scanf("%d %d %d %d %lld", &x, &y, &a, &b, &k);
        int ans = INF;
        int no_xy = lca_len(a, b);
        int has_xy = min(lca_len(a, x) + lca_len(b, y), lca_len(a, y) + lca_len(b, x)) + 1;
        if(no_xy % 2 == k % 2) ans = no_xy;
        if(has_xy % 2 == k % 2) ans = min(ans, has_xy);
        if(ans <= k) puts("YES");
        else puts("NO");
    }
    return 0;
}
posted @ 2020-02-19 10:45  Cyan_Cloud  阅读(149)  评论(0编辑  收藏  举报