倍增lca爆0
查看原帖
倍增lca爆0
542199
dxt_楼主2024/1/21 08:44

系统维护没法看前人的经验qwq

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct edge{
    int next,to;
}a[N<<1];
int cnt,head[N],h[N],p[N][20];//h(ide)是高度,p(arent)是N节点向上2的i次方所得的节点 
int n,q;
void add(int u,int v){
    a[++cnt].next=head[u];
    a[cnt].to=v;
    head[u]=cnt;
}
void dfs(int u,int fa){
	h[u]=h[fa]+1;//深度+1
	p[u][0]=fa;
	for(int i=1;(1<<i)<=h[u];++i) p[u][i]=p[p[u][i-1]][i-1];
	for(int i=head[u];i;i=a[i].next) if(fa!=a[i].to) dfs(a[i].to,u); 
}
int lca(int u,int v){
	int d=abs(h[u]-h[v]);
	for(int i=0;(1<<i)<=d;++i)
	if(d&(1<<i)) u=p[u][i];//调到同一个高度
	for(int i=17;i>=0;--i){
		if(p[u][i]!=p[v][i])//如果向上跳2的i次方个节点后还不是相同的祖先
		u=p[u][i],v=p[v][i];//那就向上跳 
	}//最后由于2的i次方等于那玩意 
	return p[u][0];//所以还要向上2的0次方 
} 
int main(){
    scanf("%d%d",&n,&q);
	for(int i=1;i<n;++i){
		int u,v;
		scanf("%d%d",&u,&v);//这道题。。。似乎是无向图 
		add(u,v);add(v,u);
	}
	dfs(1,1);
	for(int i=1;i<=q;++i){
		int a,b,c,d;
		scanf("%d%d%d%d",&a,&b,&c,&d); 
		int x=lca(a,b);int y=lca(c,d);//我们可以发现如果路径交叉那么a,b的lca一定交c,d
		if(x==y){
			printf("Y\n");
			continue;
		}
		if(h[x]>h[y]){//那么一定是x点交在cd路径上 
			if(lca(c,x)==x||lca(d,x)==x) printf("Y\n");
			else printf("N\n"); 
		}
		if(h[x]<h[y]){//那么一定是y点交ab路径上 
			if(lca(c,y)==y||lca(d,y)==y) printf("Y\n");
			else printf("N\n"); 
		}
	}
    return 0;
}
2024/1/21 08:44
加载中...