codeforces 519E A and B and Lecture Rooms LCA倍增
Description
A and B are preparing themselves for programming contests.
The University where A and B study is a set of rooms connected by corridors. Overall, the University has n rooms connected by n - 1corridors so that you can get from any room to any other one by moving along the corridors. The rooms are numbered from 1 to n.
Every day А and B write contests in some rooms of their university, and after each contest they gather together in the same room and discuss problems. A and B want the distance from the rooms where problems are discussed to the rooms where contests are written to be equal. The distance between two rooms is the number of edges on the shortest path between them.
As they write contests in new rooms every day, they asked you to help them find the number of possible rooms to discuss problems for each of the following m days.
Input
The first line contains integer n (1 ≤ n ≤ 105) — the number of rooms in the University.
The next n - 1 lines describe the corridors. The i-th of these lines (1 ≤ i ≤ n - 1) contains two integers ai and bi (1 ≤ ai, bi ≤ n), showing that the i-th corridor connects rooms ai and bi.
The next line contains integer m (1 ≤ m ≤ 105) — the number of queries.
Next m lines describe the queries. The j-th of these lines (1 ≤ j ≤ m) contains two integers xj and yj (1 ≤ xj, yj ≤ n) that means that on the j-th day A will write the contest in the room xj, B will write in the room yj.
Output
In the i-th (1 ≤ i ≤ m) line print the number of rooms that are equidistant from the rooms where A and B write contest on the i-th day.
Sample Input
4
1 2
1 3
2 4
1
2 3
1
4
1 2
2 3
2 4
2
1 2
1 3
0
2
Hint
in the first sample there is only one room at the same distance from rooms number 2 and 3 — room number 1.
思路:
题意:给你一棵有n个节点的树,m个询问,每个询问a,b,求树中到a,b距离相等的节点个数
我们先使得deg[a] >= deg[b]
首先,若a~b之间的距离为奇数的话,找不到唯一的中点,此时答案为0
(怎么求a~b之间的距离呢?预处理节点i到根的距离(此处为深度)deg[i],求出lcaq = lca(a,b);
那么dist(a,b) = deg[a] - deg[lcaq] + deg[b] - deg[lcaq];)
否则:找出ab路径的中点mid,calc(u, d)可以找出节点u的深度为d的祖先,也就是我们求出中点的深度就可以找出中点!
怎么求中点的深度dmid?通过画图可知:
dmid = dist(a,b) / 2 - deg[b] + 2 * deg[lcaq];
最终答案的计算:num[i]表示以节点i为根的子树的节点总数
若a和b的深度相同,那么ans = num[lcaq] - num[xa] - num[xb]; 其中xa是lcaq在a~lcaq的下一个节点,xb是lcaq在b~lcaq的下一个节点
若a和b深度不同,那么ans = num[mid] - num[k], 其中k表示ab的中点的下一位置(在a和b路径上靠近a的下一位置),画图可以理解。
#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 5;
struct edge {
int v, to;
edge() {};
edge(int v, int to) : v(v), to(to) {};
}e[N << 1];
int head[N], num[N], deg[N], tot, n, m;
int p[N][30]; void init()
{
memset(head, -1, sizeof head);
memset(p, -1, sizeof p);
tot = 0;
}
void addedge(int u, int v)
{
e[tot] = edge(v, head[u]);
head[u] = tot++;
}
void dfs(int u, int fa, int d)
{
deg[u] = d; p[u][0] = fa; num[u] = 1;
for(int i = head[u]; ~i; i = e[i].to) {
int v = e[i].v;
if(v != fa) {
dfs(v, u, d + 1);
num[u] += num[v];
}
}
}
void pre()
{
for(int j = 0; (1 << j) <= n; ++j)
for(int i = 1; i <= n; ++i) {
if(p[i][j - 1] != -1)
p[i][j] = p[ p[i][j - 1] ][j - 1];
}
} int calc(int u, int d) ///返回节点u的深度为d的祖先
{
for(int j = 25; j >= 0; --j) {
if(deg[u] - (1 << j) >= d) u = p[u][j];
}
return u;
}
int lca(int a, int b)
{
a = calc(a, deg[b]);///使a和b处在同一层
if(a == b) return a; ///若此时a和b相等,那么lca就是a
///否则a和b同时向上爬
for(int j = 25; j >= 0; --j) {
if(p[a][j] != -1 && p[a][j] != p[b][j]) {
a = p[a][j];
b = p[b][j];
}
}
return p[a][0];
}
int main()
{
while(~scanf("%d", &n))
{
init();
int u, v;
for(int i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(1, -1, 0);
pre(); scanf("%d", &m);
int a, b;
while(m --)
{
scanf("%d%d", &a, &b);
if(deg[a] < deg[b]) swap(a, b);
if(a == b) { printf("%d\n", n); continue; }
int lcaq = lca(a, b);
int dist = deg[a] + deg[b] - 2 * deg[lcaq]; ///a和b之间的距离
if(dist & 1) { puts("0"); continue; }
if(deg[a] == deg[b]) { ///xa和xb分别是在a~lca和b~lca的路径上距离lca为1的点
int xa = calc(a, deg[lcaq] + 1);
int xb = calc(b, deg[lcaq] + 1);
printf("%d\n", n - num[xa] - num[xb]);
}
else {
int mid = dist / 2 - deg[b] + 2 * deg[lcaq]; ///mid为ab之间的路径的中点的深度
printf("%d\n", num[ calc(a, mid) ] - num[ calc(a, mid + 1) ]);
}
}
}
return 0;
}
codeforces 519E A and B and Lecture Rooms LCA倍增的更多相关文章
- codeforces 519E A and B and Lecture Rooms(LCA,倍增)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud E. A and B and Lecture Rooms A and B are ...
- Codeforces 519E A and B and Lecture Rooms
http://codeforces.com/contest/519/problem/E 题意: 给出一棵树和m次询问,每次询问给出两个点,求出到这两个点距离相等的点的个数. 思路: lca...然后直 ...
- CodeForces 519E A and B and Lecture Rooms(倍增)
A and B are preparing themselves for programming contests. The University where A and B study is a s ...
- Codeforces 519E A and B and Lecture Rooms [倍增法LCA]
题意: 给你一棵有n个节点的树,给你m次询问,查询给两个点,问树上有多少个点到这两个点的距离是相等的.树上所有边的边权是1. 思路: 很容易想到通过记录dep和找到lca来找到两个点之间的距离,然后分 ...
- [codeforces 519E]E. A and B and Lecture Rooms(树上倍增)
题目:http://codeforces.com/problemset/problem/519/E 题意:给你一个n个点的树,有m个询问(x,y),对于每个询问回答树上有多少个点和x,y点的距离相等 ...
- A and B and Lecture Rooms(LCA)
题目描述 A and B are preparing themselves for programming contests. The University where A and B study i ...
- Codeforces Round #294 (Div. 2) A and B and Lecture Rooms(LCA 倍增)
A and B and Lecture Rooms time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- [CF Round #294 div2] E. A and B and Lecture Rooms 【树上倍增】
题目链接:E. A and B and Lecture Rooms 题目大意 给定一颗节点数10^5的树,有10^5个询问,每次询问树上到xi, yi这两个点距离相等的点有多少个. 题目分析 若 x= ...
- CodeForces 519E 树形DP A and B and Lecture Rooms
给出一棵树,有若干次询问,每次询问距两个点u, v距离相等的点的个数. 情况还挺多的,少侠不妨去看官方题解.^_^ #include <iostream> #include <cst ...
随机推荐
- ACdream 1224 Robbers (贪心)
一道贪心题,很久前做的,代码是我以前写的. 题意:有n个抢劫者抢劫了m块金子,然后第i个人平分xi/y块金子,但是会有除不尽的情况而金子不可再分,那么每个人都有一个不满意度fabs(xi / y - ...
- CSS应用给网页元素的几种方式总结
一.内联式样式表 直接在HTML标签中使用style进行定义样式.如:<p style="color:red;">这里是红色文字</p>. 二.嵌入式样式表 ...
- [Android] 如何查看apk需要支持的Android版本
reference to : http://blog.csdn.net/huiguixian/article/details/39928089 如果有一个apk,需要知道他最低安装支持的Android ...
- [Android] adb shell dumpsys的使用
reference to :http://blog.csdn.net/g19920917/article/details/38032413 有两种方法可以查看service list: 1. adb ...
- 【2016-08-21】Linux内核版本编号规则简介
我们已经了解可以使用下面的几天命令来查看Linux内核版本及Ubuntu发行版本的信息: uname -r uname -a cat /proc/version lsb-release -a 等等 可 ...
- 添加thrust的库后出错
在添加thrust库中的host_vector.h等头文件时 C:\NVIDIA\cudatoolkit\include\thrust\detail\config中的debug.h一直出问题,因此注释 ...
- 模拟赛1101d1
完美的序列(sequence)Time Limit:1000ms Memory Limit:64MB题目描述LYK 认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同.然而并不是所有的 ...
- Destination Host Unreachable
自己的Linux 机器连不上服务器了,ping XXXX的时候报这个错误了 看了一下是因为IP的原因==>进入Linux的图形界面==>System==>Administration ...
- orcad candence 快捷键小结
- JS中级 - 03:文档宽高及窗口事件(选)
可视区尺寸 document.documentElement.clientWidth document.documentElement.clientHeight 滚动距离 document.body. ...