#树链剖分,LCA#洛谷 3398 仓鼠找sugar

题目

多次询问求树上的两条路径是否有公共点


分析

有公共点当且仅当一条路径的LCA在另一条路径上,
否则一定会形成一个环,那树剖求LCA判断一下LCA是否在另一条路径上即可


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100101;
struct node{int y,next;}e[N<<1];
int k=1,n,as[N],fat[N],dep[N],tot;
int son[N],dfn[N],top[N],big[N],m;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline void dfs1(int x,int fa){
	dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
	for (rr int i=as[x],mson=-1;i;i=e[i].next)
	if (e[i].y!=fa){
		dfs1(e[i].y,x);
		son[x]+=son[e[i].y];
		if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
	}
}
inline void dfs2(int x,int linp){
	dfn[x]=++tot,top[x]=linp;
	if (!big[x]) return; dfs2(big[x],linp);
	for (rr int i=as[x];i;i=e[i].next)
	if (e[i].y!=fat[x]&&e[i].y!=big[x])
	    dfs2(e[i].y,e[i].y);
}
inline signed lca(int x,int y){
	while (top[x]!=top[y]){
		if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
		x=fat[top[x]];
	}
	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
	return x;
}
inline signed dist(int x,int y){
	rr int LCA=lca(x,y);
	return dep[x]+dep[y]-2*dep[LCA];
}
signed main(){
	n=iut(); m=iut();
	for (rr int i=1;i<n;++i){
		rr int x=iut(),y=iut();
		e[++k]=(node){y,as[x]},as[x]=k,
		e[++k]=(node){x,as[y]},as[y]=k;
	}
	dfs1(1,0),dfs2(1,0);
	for (rr int i=1;i<=m;++i,putchar(10)){
		rr int lx=iut(),ly=iut(),rx=iut(),ry=iut();
		rr int lcal=lca(lx,ly),lcar=lca(rx,ry);
		if (dist(lx,lcar)+dist(lcar,ly)==dist(lx,ly)){
			putchar('Y'); continue;
		}
		if (dist(rx,lcal)+dist(ry,lcal)==dist(rx,ry)){
			putchar('Y'); continue;
		}
		putchar('N');
	}
	return 0;
}
posted @ 2020-10-15 18:19  lemondinosaur  阅读(71)  评论(0编辑  收藏  举报