题目链接:
http://172.16.0.132/senior/#main/show/5852
题目:
题目大意:
多组询问,每次询问树上两条链是否相交
题解:
两条链相交并且仅当某一条链的两个端点的LCA在另一个端点上
对于每次询问,我们分别处理出两条链端点的LCA,通过倍增判断是否存在一条链的LCA在另一条链上
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> using namespace std; const int N=1e5+15; int n,tot; int h[N],fa[N][20],dep[N]; struct E{ int to,nxt; }e[N<<1]; inline int read(){ char ch=getchar();int s=0,f=1; while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();} return s*f; } void link(int u,int v){e[++tot]=(E){v,h[u]};h[u]=tot;} void dfs(int x,int pre){ for (int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=h[x],y;i;i=e[i].nxt){ if ((y=e[i].to)==pre) continue; fa[y][0]=x;dep[y]=dep[x]+1; dfs(y,x); } } int lca(int x,int y){ if (dep[x]<dep[y]) swap(x,y); for (int i=19;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if (x==y) return x; for (int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } bool chk(int a,int b,int La,int Lb){ if (dep[Lb]<dep[La]) return 0; if (dep[a]>=dep[Lb]){ for (int i=19;i>=0;i--) if (dep[fa[a][i]]>=dep[Lb]&&dep[fa[a][i]]>=dep[La]) a=fa[a][i]; if (a==Lb) return 1; } if (dep[b]>=dep[Lb]){ for (int i=19;i>=0;i--) if (dep[fa[b][i]]>=dep[Lb]&&dep[fa[b][i]]>=dep[La]) b=fa[b][i]; if (b==Lb) return 1; } return 0; } int main(){ freopen("inter.in","r",stdin); freopen("inter.out","w",stdout); n=read(); for (int i=1,u,v;i<n;i++){ u=read();v=read(); link(u,v);link(v,u); } dep[1]=1;dfs(1,0); int q=read(); while (q--){ int a=read(),b=read(),c=read(),d=read(); int lab=lca(a,b),lcd=lca(c,d); //printf("%d %d ",lab,lcd); if (chk(a,b,lab,lcd)||chk(c,d,lcd,lab)) puts("YES"); else puts("NO"); } return 0; }