[JZOJ 5852] 相交

题意:求树上两条路径有无祖先。
思路:
瞎搞\(LCA\)啊。。。
可惜我\(LCA\)打错了,我居然调了半小时...qwq

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
#define travel(i,x) for(int i = head[x];i;i=e[i].nxt)
inline int read () {
	int q=0,f=1;char ch = getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;ch=getchar();
	}
	while(isdigit(ch)){
		q=q*10+ch-'0';ch=getchar();
	}
	return q*f;
} 
struct edge {
	int to;
	int nxt;
}e[maxn << 1];
int cnt;
int head[maxn << 1];
inline void add(int u,int v) {
	e[++cnt].to = v;
	e[cnt].nxt = head[u];
	head[u] = cnt;
}
int f[maxn][30];
int dep[maxn << 1];
inline void dfs(int x,int fa) {
	dep[x] = dep[fa] + 1;
	travel(i,x) {
		int y = e[i].to;
		if(y != fa) {
			f[y][0] = x;
			for(int j = 1;j <= 20; ++j) {
				f[y][j] = f[f[y][j - 1]][j - 1];
			}
			dfs(y,x);
		}
	}
}
inline int lca(int x,int y) {
	if(dep[x] < dep[y]) swap(x,y);
	for(int i = 20;i >= 0; --i) {
		if(dep[f[x][i]] >= dep[y]) x = f[x][i];
	}
	if(x == y) return x;
	for(int i = 20; i >= 0; --i) {
		if(f[x][i] != f[y][i]) {
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
int n,m;
int main () {
	freopen("inter.in","r",stdin);
	freopen("inter.out","w",stdout);
	n = read();
	for(int i = 1;i < n; ++i) {
		int x = read(),y = read();
		add(x,y);add(y,x);
	}
	dfs(1,0);
	m = read();
	while(m--) {	
		int x = read(),y = read();
		int LCA = lca(x,y);
		int l = read(),r = read();
		int _LCA = lca(l,r);
		//cout<<"LCA:"<<LCA<<' '<<_LCA<<endl;
		int Grand_LCA = lca(LCA,_LCA);
		if(LCA == _LCA) {
			puts("YES");
		}
		else if(Grand_LCA == _LCA && (lca(l,LCA) == LCA || lca(r,LCA) == LCA)) {
			puts("YES");
		}
		else if(Grand_LCA == LCA && (lca(x,_LCA) == _LCA || lca(y,_LCA) == _LCA)) {
			puts("YES");
		}
		else puts("NO");
	}
	return 0;
}

原文地址:https://www.cnblogs.com/akoasm/p/9607335.html