CF519E A and B and Lecture Rooms
2018-09-29 10:43
309 查看
这道题目...真是一道好题...题出的好!难度适中!覆盖知识点广!题目有着切合实际的背景!解法比较自然!给出题人点赞 !
题意:
给你一棵树,每次询问给出两个点,问树上有多少点到这两个点的距离相等。
$Sol$
树上距离...嗯肯定有$LCA$,但是看起来还是毫无思路的样子啊...怎么办。
这个时候分类讨论一定是个不错的选择(逃)
由于我只会树上倍增,而且大部分时候它还是很好用的,还能求出许多附属需要的东西,所以我们先用树上倍增法求出树上这两点的距离,进行分类讨论。(设置一个a的深度大于b的深度的前提)
1)当距离为奇数:无解,答案为0.
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #include<cmath> 5 #define maxn 100090 6 7 using namespace std; 8 9 int n,m,tot,t; 10 int head[maxn],size[maxn],d[maxn]; 11 int f[maxn][30]; 12 bool vis[maxn]; 13 struct node{ 14 int to,next; 15 }edge[maxn*2]; 16 17 void add(int x,int y) 18 { 19 edge[++tot].to=y; 20 edge[tot].next=head[x]; 21 head[x]=tot; 22 } 23 24 void init_1() 25 { 26 queue<int>q; 27 q.push(1);d[1]=1; 28 while(!q.empty()) 29 { 30 int u=q.front();q.pop(); 31 for(int i=head[u];i;i=edge[i].next) 32 { 33 int v=edge[i].to; 34 if(d[v]) continue; 35 d[v]=d[u]+1; 36 f[v][0]=u; 37 for(int j=1;j<=t;j++) 38 f[v][j]=f[f[v][j-1]][j-1]; 39 q.push(v); 40 } 41 } 42 } 43 44 void init_2(int u) 45 { 46 vis[u]=1;size[u]++; 47 for(int i=head[u];i;i=edge[i].next) 48 { 49 int v=edge[i].to; 50 if(vis[v]) continue; 51 init_2(v); 52 size[u]+=size[v]; 53 } 54 } 55 56 int find(int x,int dep) 57 { 58 int hu=x; 59 for(int i=t;i>=0;i--) 60 { 61 if(d[hu]-(1<<i)<dep) continue; 62 hu=f[hu][i]; 63 } 64 return hu; 65 } 66 67 int ask(int x,int y) 68 { 69 if(d[x]<d[y]) swap(x,y); 70 int prex=x,prey=y,lca=0,tmp=0; 71 for(int i=t;i>=0;i--) 72 if(d[f[x][i]]>=d[y]) x=f[x][i]; 73 if(x==y) lca=x; 74 else 75 { 76 for(int i=t;i>=0;i--) 77 if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; 78 lca=f[x][0]; 79 } 80 x=prex,tmp=y,y=prey; 81 int dis=d[x]+d[y]-2*d[lca]; 82 if(dis&1) return 0; 83 if(lca==y) 84 { 85 int mid=(d[x]+d[y])>>1; 86 return size[find(x,mid)]-size[find(x,mid+1)]; 87 } 88 else 89 { 90 if(d[x]==d[y]) 91 return n-size[find(x,d[lca]+1)]-size[find(y,d[lca]+1)]; 92 else 93 { 94 int mid=d[x]-(dis>>1); 95 return size[find(x,mid)]-size[find(x,mid+1)]; 96 } 97 } 98 } 99 100 int main() 101 { 102 scanf("%d",&n); 103 t=log2(n)+1; 104 for(int i=1;i<=n-1;i++) 105 { 106 int x=0,y=0; 107 scanf("%d%d",&x,&y); 108 add(x,y);add(y,x); 109 } 110 init_1(); 111 init_2(1); 112 scanf("%d",&m); 113 for(int i=1;i<=m;i++) 114 { 115 int x=0,y=0; 116 scanf("%d%d",&x,&y); 117 if(x==y){printf("%d\n",n);continue;} 118 printf("%d\n",ask(x,y)); 119 } 120 return 0; 121 }View Code
参考文献:https://www.cnblogs.com/qixingzhi/p/9302038.html(从这里学会的)
相关文章推荐
- Codeforces Round #294 (Div. 2) E. A and B and Lecture Rooms(lca+思维,树上寻找与给定两个点距离相等的点的个数)
- Codeforces Round #294 (Div. 2) A and B and Lecture Rooms(LCA 倍增)
- 在线LCA 倍增法 Codeforces Round #294 (Div. 2) E - A and B and Lecture Rooms
- Codeforces 519E A and B and Lecture Rooms [倍增法LCA]
- codeforces 519E A and B and Lecture Rooms
- [codeforces 519E]E. A and B and Lecture Rooms(树上倍增)
- Codeforces519 E. A and B and Lecture Rooms
- Codeforces Round #294 (Div. 2)-E. A and B and Lecture Rooms
- [CodeForces519E]A and B and Lecture Rooms(lca)
- 【Henu ACM Round#15 E】 A and B and Lecture Rooms
- 【LCA】 Codeforces Round #294 (Div. 2) E. A and B and Lecture Rooms
- Codeforces Round #294 (Div. 2) E. A and B and Lecture Rooms
- Codeforces Round #294 (Div. 2)-E. A and B and Lecture Rooms(LCA倍增)
- CodeForces 519E A and B and Lecture Rooms
- LCA好(Codeforces Round #294 (Div. 2)E. A and B and Lecture Rooms)
- [CF Round #294 div2] E. A and B and Lecture Rooms 【树上倍增】
- CF 294 div2 E. A and B and Lecture Rooms (LCA)
- Codeforces Round #294 (Div. 2)---E. A and B and Lecture Rooms
- CF519E - A and B and Lecture Rooms
- [codefoces519E]A and B and Lecture Rooms(lca)