CodeForces-1304E 1-Trees and Queries
1-Trees and Queries
LCA 倍增 + 思维
因为这里的路径不是简单路径,因此只要符合最短路径长度 不大于 \(k\),且最短路径长度与 \(k\) 的奇偶性相同,就必定有路径可以到(反复走一步,退一步)
加入一条边之后,可能会产生另一条路径的奇偶性与最短路径的奇偶性不同,因此我们考虑检测三种路径与 \(k\) 的关系(大小 与 奇偶性)
-
考虑从 \(a\) 到 \(b\) 的最短路径
-
考虑 \(a->x\), \(x->y\), \(y->b\) 的最短路径
-
考虑 \(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;
}

浙公网安备 33010602011771号