P3398 仓鼠找sugar
仓鼠找sugar
一道提高+/省选-的题目,终于可以提高博客题目的平均难度了。。。
大致题意就是在一棵树上有两条路径,询问这两个路径是不是可以相交。
而如果两条路径相交的话,一定有一条路径a两端点的LCA在另一条的路径上,我们可以通过求路径a的LCA是不是在路径b上来求出a与b是不是相交的。
根据以上推断,可以保证了路径a的LCA的深度一定大于路径b的LCA的深度。只要再在确定路径a的LCA与路径b的两端点其中一点的LCA是路径a的LCA就确保路径a的LCA在路径b上了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #define N 100010 4 #define M 200010 5 using namespace std; 6 int next[M],to[M],num,head[N],size[N],father[N],deep[N],top[N],n,m,a,b,c,d,lca_a_b,lca_c_d; 7 void add(int false_from,int false_to){ 8 next[++num]=head[false_from]; 9 to[num]=false_to; 10 head[false_from]=num; 11 } 12 void dfs1(int x){ 13 size[x]=1; 14 deep[x]=deep[father[x]]+1; 15 for(int i=head[x];i;i=next[i]) 16 if(father[x]!=to[i]){ 17 father[to[i]]=x; 18 dfs1(to[i]); 19 size[x]+=size[to[i]]; 20 } 21 } 22 void dfs2(int x){ 23 int mmax=0; 24 if(!top[x]) 25 top[x]=x; 26 for(int i=head[x];i;i=next[i]) 27 if(father[x]!=to[i]&&size[to[i]]>size[mmax]) 28 mmax=to[i]; 29 if(mmax){ 30 top[mmax]=top[x]; 31 dfs2(mmax); 32 } 33 for(int i=head[x];i;i=next[i]) 34 if(father[x]!=to[i]&&to[i]!=mmax) 35 dfs2(to[i]); 36 } 37 int lca(int x,int y){ 38 while(top[x]!=top[y]){ 39 if(deep[top[x]]<deep[top[y]]) 40 swap(x,y); 41 x=father[top[x]]; 42 } 43 if(deep[x]<deep[y])return x; 44 return y; 45 } 46 int main(){ 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<n;++i){ 49 scanf("%d%d",&a,&b); 50 add(a,b); 51 add(b,a); 52 } 53 dfs1(1); 54 dfs2(1); 55 for(int i=1;i<=m;++i){ 56 scanf("%d%d%d%d",&a,&b,&c,&d); 57 lca_a_b=lca(a,b); 58 lca_c_d=lca(c,d); 59 if(deep[lca_a_b]==deep[lca_c_d]){ 60 if(lca_a_b==lca_c_d){ 61 printf("Y\n"); 62 continue; 63 } 64 printf("N\n"); 65 continue; 66 } 67 if(deep[lca_a_b]<deep[lca_c_d]){ 68 if(lca(lca_c_d,a)==lca_c_d||lca(lca_c_d,b)==lca_c_d) 69 printf("Y\n"); 70 else 71 printf("N\n"); 72 } 73 if(deep[lca_a_b]>deep[lca_c_d]){ 74 if(lca(lca_a_b,c)==lca_a_b||lca(lca_a_b,d)==lca_a_b) 75 printf("Y\n"); 76 else 77 printf("N\n"); 78 } 79 } 80 return 0; 81 }