洛谷 3398 仓鼠找sugar 【模板】判断树上两链有交
【题解】
题意就是判断树上两条链是否有交。口诀是“判有交,此链有彼祖”。即其中一条链的端点的Lca在另一条链上。
我们设两条链的端点的Lca中深度较大的为L2,对L2与另一条链的两个端点分别求Lca,若满足其中一个Lca等于L2,即表示两链有交。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 #define rg register 6 #define N 500010 7 using namespace std; 8 int n,m,tot,last[N],siz[N],fa[N],dep[N],hvy[N],top[N]; 9 struct edge{ 10 int to,pre; 11 }e[N<<1]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 void dfs1(int x){ 19 siz[x]=1; dep[x]=dep[fa[x]]+1; 20 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]){ 21 fa[to]=x; dfs1(to); siz[x]+=siz[to]; 22 if(siz[to]>siz[hvy[x]]) hvy[x]=to; 23 } 24 } 25 void dfs2(int x,int tp){ 26 top[x]=tp; 27 if(hvy[x]) dfs2(hvy[x],tp); 28 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]&&to!=hvy[x]) 29 dfs2(to,to); 30 } 31 inline int lca(int x,int y){ 32 int t1=top[x],t2=top[y]; 33 while(t1!=t2){ 34 if(dep[t1]<dep[t2]) swap(t1,t2),swap(x,y); 35 x=fa[t1]; t1=top[x]; 36 } 37 return dep[x]<dep[y]?x:y; 38 } 39 int main(){ 40 n=read(); m=read(); 41 for(rg int i=1;i<n;i++){ 42 int u=read(),v=read(); 43 e[++tot]=(edge){v,last[u]}; last[u]=tot; 44 e[++tot]=(edge){u,last[v]}; last[v]=tot; 45 } 46 dfs1(1); dfs2(1,1); 47 while(m--){ 48 int a=read(),b=read(),x=read(),y=read(); 49 int L1=lca(a,b),L2=lca(x,y); 50 if(dep[L1]>dep[L2]) swap(L1,L2),swap(a,x),swap(b,y); 51 puts(lca(L2,a)==L2||lca(L2,b)==L2?"Y":"N"); 52 } 53 return 0; 54 }