CodeForces 1304E 1-Trees and Queries LCA

一、内容

Gildong was hiking a mountain, walking by millions of trees. Inspired by them, he suddenly came up with an interesting idea for trees in data structures: What if we add another edge in a tree?Then he found that such tree-like graphs are called 1-trees. Since Gildong was bored of solving too many tree problems, he wanted to see if similar techniques in trees can be used in 1-trees as well. Instead of solving it by himself, he's going to test you by providing queries on 1-trees.First, he'll provide you a tree (not 1-tree) with nvertices, then he will ask you q queries. Each query contains 5 integers: x, y, a, b, and k. This means you're asked to determine if there exists a path from vertex a to b that contains exactly k edges after adding a bidirectional edge between vertices x and y. A path can contain the same vertices and same edges multiple times. All queries are independent of each other; i.e. the added edge in a query is removed in the next query.

Input

The first line contains an integer n(3≤n≤105), the number of vertices of the tree.Next n−1lines contain two integers u and v (1≤u,v≤n, u≠v) each, which means there is an edge between vertex u and v. All edges are bidirectional and distinct.Next line contains an integer (1≤q≤105), the number of queries Gildong wants to ask.Next qlines contain five integers x, y, a, b, and k each (1≤x,y,a,b≤n, x≠y, 1≤k≤109) – the integers explained in the description. It is guaranteed that the edge between x and y does not exist in the original tree.

Output

For each query, print "YES" if there exists a path that contains exactly kedges from vertex a to b after adding an edge between vertices x and y Otherwise, print "NO".

You can print each letter in any case (upper or lower).

Example

Input

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

Output

YES
YES
NO
YES
NO

二、思路

  • 由于添加一条边x -->y, 那么a–>b的路径就会有3条
  • 第一条: a直接到b
  • 第二条:a–>x, x通过外接边到y, y–>b
  • 第三条:a–>y, y通过外界变到x, x–>b
  • 只要k- a到b的路径长度 >= 0 并且 是偶数 代表可以YES。 因为偶数的话,和旁边任意一点来回消耗就行了

三、代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5, M = N * 2;
struct E {int v, next;} e[M];
int n, m, k, lg, x, y, a, b, len, h[N], f[N][20], dep[N];
void add(int u, int v) {e[++len].v = v; e[len].next = h[u]; h[u] = len;}
void bfs() {
	lg = int(log(n) / log(2)) + 1;
	queue<int> q; q.push(1); dep[1] = 1;
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int j = h[u]; j; j = e[j].next) {
			int v = e[j].v;
			if (dep[v]) continue;
			dep[v] = dep[u] + 1;
			f[v][0] = u; q.push(v);
			for (int k = 1; k <= lg; k++) f[v][k] = f[f[v][k - 1]][k - 1];
		}
	}
}
int LCA(int x, int y) {
	if (dep[y] > dep[x]) swap(x, y);
	for (int k = lg; k >= 0; k--) {
		if (dep[f[x][k]] >= dep[y]) x = f[x][k]; 	
	}
	if (x == y) return x;
	for (int k = lg; k >= 0; k--) {
		if (f[x][k] != f[y][k]) x = f[x][k], y = f[y][k];
	}
	return f[x][0];
}
int dlen(int x, int y) {
	return dep[x] + dep[y] - 2 * dep[LCA(x, y)];
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i < n; i++) {
		scanf("%d%d", &a, &b);
		add(a, b); add(b, a);
	}
	bfs();
	scanf("%d", &m);
	while (m--) {
		scanf("%d%d%d%d%d", &x, &y, &a, &b, &k);
		int dis1 = k - dlen(a, b); 
		int dis2 = k - (dlen(a, x) + 1 + dlen(y, b)); 
		int dis3 = k - (dlen(a, y) + 1 + dlen(x, b)); 
		if ((dis1 >= 0 && dis1 % 2 == 0) || (dis2 >= 0 && dis2 % 2 == 0) || (dis3 >= 0 && dis3 % 2 == 0) ) printf("YES\n");
		else printf("NO\n");
	} 
	return 0;
} 
发布了456 篇原创文章 · 获赞 466 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_41280600/article/details/104339466