洛谷 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 }
View Code

 

  

转载于:https://www.cnblogs.com/DriverLao/p/9301130.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值