Evanyou Blog 彩带

洛谷P3398 仓鼠找suger

传送门啦

思路:

那么从 $ A $ 到 $ B $ 可以分解成 先从 $ A $ 到 $ X $ 再从 $ X $ 到 $ B $ 。。。 另一个同理

假设能相遇 那么
要么在 $ A $ 到 $ X $ 的过程 $ A,B $ 相遇 要么在 $ X $ 到 $ B $ 的过程 $ A,B $ 相遇
对于在 $ A $ 到 $ X $ 的过程相遇的情况 又可以分解为:
情况1:
在 $ A $ 到 $ X $ 的过程和 $ C $ 到 $ Y $ 的过程 中 $ A,B $ 相遇
情况2:
在 $ A $ 到 $ X $ 的过程和 $ Y $ 到 $ D $ 的过程 中 $ A,B $ 相遇

呃呃呃。。。

相遇的情况 :
$ a->X , c->Y $ 相遇(可以认为 松鼠和他基友都在网上冲)
$ a->X,Y->d $ 相遇(一个往上冲,一个在往下冲)
$ X->b,c->Y $ 相遇(一个往下冲 一个往上冲)
$ X->b,Y->d $ 相遇(都往下冲)
根据树中的每一个节点的父亲都是唯一的, $ lca $ 可以认为是他们最短路径上深度最浅的那个点, $ a,b,c,d $ 到他们 $ lca $ 的路径是唯一的。

而上述的 $ 4 $ 个 $ lca $ 中深度最大的那一个 我们姑且记为 $ S $ ,那么 $ S $ 一定是 $ a,b $ 中的一个和 $ c,d $ 的一个的 $ lca $ (我们假设是 $ lca(a,d) $ )

那么如果 $ S $ 的深度大于 $ x,y $ 中较大的的那一个,说明 $ a $ 在和 $ d $ 在往上冲的过程中一定要经过他们的 $ lca $ ,也就是 $ S $ ,再经过 $ x $ 或者是 $ y $ 。因为 $ a $ 和 $ d $ 是 $ a,b $ 中的一个和 $ c,d $ 中的一个,他们还要冲向 $ X $ 或者是 $ Y $ 。这种情况必然相遇;

在 $ X 、Y $ 中取一个最大,再在 $ lca(a,c).lca(a,d),lca(b,c),lca(b,d) $ 这四个当中取一个最大,如果后者的深度大于等于前者,那么可以相遇,否则不能;

#include <iostream> 
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define re register
using namespace std ;
const int maxn = 5 * 1e5 + 4 ;

inline int read () {
	int f = 1 , x = 0 ;
	char ch = getchar () ;
	while (ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
	return x * f ;
}

int n , q , u , v , a , b , c , d ;
int head[maxn] , tot ;

struct Edge {
	int from , to , next ;
}edge[maxn << 1] ;

inline void add (int u , int v) {
	edge[++tot].from = u ;
	edge[tot].to = v ;
	edge[tot].next = head[u] ;
	head[u] = tot ;
}

int dep[maxn] , f[maxn][21] ;

inline void dfs (int x , int fa) {
	dep[x] = dep[fa] + 1 ;
	f[x][0] = fa ;
	for(re int i = 1 ; (1 << i) <= dep[x] ; ++ i) {
		f[x][i] = f[f[x][i - 1]][i - 1] ;
	}
	for(re int i = head[x] ; i ; i = edge[i].next) {
		int v = edge[i].to ;
		if(v != fa) dfs(v , x) ;
	}
}

inline int lca (int a , int b) {
	if(dep[a] < dep[b])  swap(a , b) ;
	for(re int i = 18 ; i >= 0 ; -- i) {
		if((1 << i) <= (dep[a] - dep[b])) {
			a = f[a][i] ;
		}
	}
	if(a == b)  return a ;
	for(re int i = 18 ; i >= 0 ; -- i) {
		if((1 << i) <= dep[a] && f[a][i] != f[b][i]) {
			a = f[a][i] ;
			b = f[b][i] ;
		}
	}
	return f[a][0] ; 
}

int main () {
	n = read () ; q = read () ;
	for(re int i = 1 ; i <= n - 1 ; ++ i) {
		u = read () ; v = read () ;
		add(u , v) ;
		add(v , u) ;
	}
	dfs(1 , 1) ; 
	for(re int i = 1 ; i <= q ; ++ i) {
		a = read () ; b = read () ; c = read () ; d = read () ;
		int fm1 = max(dep[lca(a , b)] , dep[lca(c , d)]) ;
		int fm2 = max(max(dep[lca(a , c)] , dep[lca(a , d)]) , max(dep[lca(b , c)] , dep[lca(b , d)])) ;
        if(fm2 >= fm1)
			printf("Y\n");
        else
    		printf("N\n");
	}
	return 0 ;
}
posted @ 2019-02-26 19:23  Stephen_F  阅读(206)  评论(1编辑  收藏  举报