P3398 仓鼠找sugar
很基础的lca题。
关键是弄明白什么时候两人会相遇,即什么情况下a-b与c-d的路径会相交
首先默认dep[a]>dep[b],dep[c]>dep[d],
那么一共有四种情况相交
if(lca(a,lca2)==lca2&&lca3==lca1) flag=1;
if(lca(b,lca2)==lca2&&lca3==lca1) flag=1;
if(lca(c,lca1)==lca1&&lca3==lca2) flag=1;
if(lca(d,lca1)==lca1&&lca3==lca2) flag=1;
其分别对应于
lca2在a-lca1的路径上
lca2在b-lca1的路径上
lca1在c-lca2的路径上
lca1在d-lca2的路径上
#include<bits/stdc++.h> using namespace std; const int maxn=100005; int tail,head[maxn],f[maxn][21],dep[maxn],n,q; struct edge { int x,y,nex; }e[400005]; void read(int &p) { p=0; int flag=1; char s=getchar(); while(!isdigit(s)) s=getchar(); for(;isdigit(s);s=getchar()) p=p*10+s-'0'; p*=flag; } void add_edge(int x,int y) { e[++tail].x=x;e[tail].y=y;e[tail].nex=head[x];head[x]=tail; } void deal_first(int x,int fa) { dep[x]=dep[fa]+1; for(int i=0;i<=19;i++) f[x][i+1]=f[f[x][i]][i]; for(int i=head[x];i;i=e[i].nex) { int y=e[i].y; if(y!=fa) { f[y][0]=x; deal_first(y,x); } } } 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 main() { #ifdef DEBUG // freopen("1.in","r",stdin); #endif read(n);read(q); int x,y; for(int i=1;i<=n-1;i++) { read(x);read(y); add_edge(x,y); add_edge(y,x); } //build a tree deal_first(1,0); //read(q); //cout<<"A"<<q<<endl; int a,b,c,d; //deal with questions for(int i=1;i<=q;i++) { int flag=0; read(a);read(b);read(c);read(d); int lca1=lca(a,b); int lca2=lca(c,d); int lca3=lca(lca1,lca2); if(lca(a,lca2)==lca2&&lca3==lca1) flag=1; if(lca(b,lca2)==lca2&&lca3==lca1) flag=1; if(lca(c,lca1)==lca1&&lca3==lca2) flag=1; if(lca(d,lca1)==lca1&&lca3==lca2) flag=1; if(flag==1) puts("Y"); else puts("N"); } return 0; }