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