洛谷P3398仓鼠找sugar
Posted Absolutezero
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3398仓鼠找sugar相关的知识,希望对你有一定的参考价值。
画个图就能多少看出些规律
证明借鉴一下大牛的题解:
设从A到B,经过的深度最小的点为X 同理,C,D的为Y
题目是一个点从A出发到B 一个从C出发到D
那么从A到B可以分解成 先从A到X 再从X到B。。。 C同理
假设能相遇 那么
要么在A到X的过程A,B相遇 要么在X到B的过程A,B相遇
对于在A到X的过程相遇的情况 又可以分解为:
情况1:
在A到X的过程和 C到Y的过程 中A,B相遇 此时相遇点的深度必然大于等于MIN(X深度,Y深度)
情况2:
在A到X的过程和 Y到D的过程 中A,B相遇 此时相遇点的深度必然大于等于MIN (X深度,Y深度)
另一种情况同理。。。
所以显然只要求出MIN=min(lca(a,b),lca(c,d));(lca返回的是两个点公共祖先的最大深度)
假如lca(a,c) lca(a,d) lca(b,c) lca(b,d) 中有任意一个大于等于MIN 的话 那么可以相遇 否则不能
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100010,M=200010,p=20; 6 int n,q,size,father[N][p+10],head[M]; 7 int nxt[M],son[M],deep[N]; 8 int read(){ 9 int sum=0; 10 char ch=getchar(); 11 while (ch<\'0\'||ch>\'9\') 12 ch=getchar(); 13 while (ch>=\'0\'&&ch<=\'9\'){ 14 sum=sum*10+ch-\'0\'; 15 ch=getchar(); 16 } 17 return sum; 18 } 19 void uni(int x,int y){ 20 size++; 21 nxt[size]=head[x]; 22 head[x]=size; 23 son[size]=y; 24 } 25 void swap(int &a,int &b){ 26 int tmp=a; 27 a=b; 28 b=tmp; 29 } 30 void dfs(int fa,int x){ 31 for (int k=head[x];k;k=nxt[k]){ 32 int y=son[k]; 33 if (y==fa) 34 continue; 35 father[y][0]=x; 36 deep[y]=deep[x]+1; 37 dfs(x,y); 38 } 39 } 40 void pre(){ 41 for (int j=1;j<=p;j++) 42 for (int i=1;i<=n;i++) 43 father[i][j]=father[father[i][j-1]][j-1]; 44 } 45 int LCA(int x,int y){ 46 if (deep[x]<deep[y]) 47 swap(x,y); 48 int d=deep[x]-deep[y]; 49 for (int j=p;j>=0;j--) 50 if (d&(1<<j)) 51 x=father[x][j]; 52 if (x==y) 53 return x; 54 for (int j=p;j>=0;j--) 55 if (father[x][j]!=father[y][j]){ 56 x=father[x][j]; 57 y=father[y][j]; 58 } 59 return father[x][0]; 60 } 61 int main(){ 62 int u,v; 63 size=0; 64 n=read(); 65 q=read(); 66 for (int i=1;i<n;i++){ 67 u=read(); 68 v=read(); 69 uni(u,v); 70 uni(v,u); 71 } 72 deep[1]=1; 73 for (int i=1;i<=n;i++) 74 father[i][0]=i; 75 dfs(1,1); 76 pre(); 77 int a,b,c,d; 78 for (int i=1;i<=q;i++){ 79 a=read(); 80 b=read(); 81 c=read(); 82 d=read(); 83 int lca=max(deep[LCA(a,b)],deep[LCA(c,d)]); 84 int l1=max(deep[LCA(a,c)],deep[LCA(a,d)]); 85 int l2=max(deep[LCA(b,c)],deep[LCA(b,d)]); 86 if (max(l1,l2)>=lca) 87 printf("Y\\n"); 88 else 89 printf("N\\n"); 90 } 91 return 0; 92 }
当然我们也可以判断一下最深的LCA是否在较浅的LCA路径之外
(比如lca_min=lca(a,b),则若deep[a]<lca_max&&deep[b]<lca_max(=lca(c,d))就在外面)
在外面肯定不能相遇
否则再判断一下它是否在其路径上
判断方法,,倍增跳点即可
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=100010,M=200010,p=20; 5 int n,q,size,father[N][p+10],head[M]; 6 int nxt[M],son[M],deep[N]; 7 int read(){ 8 int sum=0; 9 char ch=getchar(); 10 while (ch<\'0\'||ch>\'9\') 11 ch=getchar(); 12 while (ch>=\'0\'&&ch<=\'9\'){ 13 sum=sum*10+ch-\'0\'; 14 ch=getchar(); 15 } 16 return sum; 17 } 18 void uni(int x,int y){ 19 size++; 20 nxt[size]=head[x]; 21 head[x]=size; 22 son[size]=y; 23 } 24 void swap(int &a,int &b){ 25 int tmp=a; 26 a=b; 27 b=tmp; 28 } 29 void dfs(int fa,int x){ 30 for (int k=head[x];k;k=nxt[k]){ 31 int y=son[k]; 32 if (y==fa) 33 continue; 34 father[y][0]=x; 35 deep[y]=deep[x]+1; 36 dfs(x,y); 37 } 38 } 39 void pre(){ 40 for (int j=1;j<=p;j++) 41 for (int i=1;i<=n;i++) 42 father[i][j]=father[father[i][j-1]][j-1]; 43 } 44 int LCA(int x,int y){ 45 if (deep[x]<deep[y]) 46 swap(x,y); 47 int d=deep[x]-deep[y]; 48 for (int j=p;j>=0;j--) 49 if (d&(1<<j)) 50 x=father[x][j]; 51 if (x==y) 52 return x; 53 for (int j=p;j>=0;j--) 54 if (father[x][j]!=father[y][j]){ 55 x=father[x][j]; 56 y=father[y][j]; 57 } 58 return father[x][0]; 59 } 60 int check(int x,int y){ 61 for (int j=p;j>=0;j--) 62 if (deep[father[x][j]]>=deep[y]) 63 x=father[x][j]; 64 if (x==y) 65 return 1; 66 return 0; 67 }//deep[x]>deep[y] 68 int main(){ 69 int u,v; 70 size=0; 71 n=read(); 72 q=read(); 73 for (int i=1;i<n;i++){ 74 u=read(); 75 v=read(); 76 uni(u,v); 77 uni(v,u); 78 } 79 deep[1]=1; 80 father[1][0]=1; 81 dfs(0,1); 82 pre(); 83 int a,b,c,d; 84 for (int i=1;i<=q;i++){ 85 a=read(); 86 b=read(); 87 c=read(); 88 d=read(); 89 int lcax=LCA(a,b); 90 int lcay=LCA(c,d); 91 if (deep[lcax]<deep[lcay]){ 92 swap(lcax,lcay); 93 swap(a,c); 94 swap(b,d); 95 }//deep[lcax]>deep[lcay] 96 if (check(lcax,lcay)&&(check(c,lcax)||check(d,lcax))) 97 printf("Y\\n"); 98 else 99 printf("N\\n"); 100 } 101 return 0; 102 }
最后想说…………LCA的pre()函数……j 如果打错从0循环的话会很GG……
因为它会WA……不一定是RE……
以上是关于洛谷P3398仓鼠找sugar的主要内容,如果未能解决你的问题,请参考以下文章