P3398 仓鼠找sugar 题解

题目大意

给出一个(N)个点的树,给出两条路径的起点和终点,问两条路径有没有交

P3398 仓鼠找sugar

问题求解

这道题貌似是一道比较模板的题目,至于为什么蓝我就不知道了,笑

我们可以求出起点和重点的(LCA),显然,如果两条路径相交的话,一个路径的(LCA)必定在另外一条路径上

然后判断一个点是否在一个路径上要满足两个条件

  • (deep[x]≥deep[LCA(s,t)])

  • (LCA(x,s)==x||LCA(x,t)==x)

就分两种情况判断一下就好了

代码实现

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,maxe=2e5+5;
int N,Q;
int lnk[maxn],nxt[maxe],son[maxe],cnt;
int fa[maxn],size[maxn],top[maxn],dep[maxn];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
void dfs1(int x){
	size[x]=1;dep[x]=dep[fa[x]]+1;
	for(int j=lnk[x];j;j=nxt[j]){
		if(son[j]==fa[x])continue;
		fa[son[j]]=x;dfs1(son[j]);size[x]+=size[son[j]];
	}
	return ;
}
void dfs2(int x){
	int w=0;
	if(!top[x])top[x]=x;
	for(int j=lnk[x];j;j=nxt[j])if(son[j]!=fa[x]&&size[son[j]]>size[w])w=son[j];
	if(w){top[w]=top[x];dfs2(w);}
	for(int j=lnk[x];j;j=nxt[j])if(son[j]!=fa[x]&&son[j]!=w)dfs2(son[j]);
	return ;
}
int lca(int x,int y){
	for(;top[x]!=top[y];)dep[top[x]]<dep[top[y]]&&(swap(x,y),0),x=fa[top[x]];
	dep[x]>dep[y]&&(swap(x,y),0);
	return x;
}
int main(){
	N=read();Q=read();
	for(int i=1;i<N;i++){
		int x=read(),y=read();
		add_e(x,y);add_e(y,x);
	}
	dfs1(1);dfs2(1);
	for(int i=1;i<=Q;i++){
		int a=read(),b=read(),c=read(),d=read();
		int a_b=lca(a,b),c_d=lca(c,d);
		if(dep[a_b]<dep[c_d]){swap(a_b,c_d);swap(a,c);swap(b,d);}
		if(lca(a_b,c)==a_b||lca(a_b,d)==a_b)printf("Y
");
		else printf("N
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/martian148/p/15183580.html