题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822

Problem Description
Three countries, Red, Yellow, and Blue are in war. The map of battlefield is a tree, which means that there are N nodes and (N – 1) edges that connect all the nodes. Each country has a base station located in one node. All three countries will not place their station in the same node. And each country will start from its base station to occupy other nodes. For each node, country A will occupy it iff other two country's base stations have larger distances to that node compared to country A. Note that each edge is of the same length.

Given three country's base station, you task is to calculate the number of nodes each country occupies (the base station is counted).

 
Input
The input starts with a single integer T (1 ≤ T ≤ 10), the number of test cases.
Each test cases starts with a single integer N (3 ≤ N ≤ 10 ^ 5), which means there are N nodes in the tree.
Then N - 1 lines follow, each containing two integers u and v (1 ≤ u, v ≤ N, u ≠ v), which means that there is an edge between node u and node v.
Then a single integer M (1 ≤ M ≤ 10 ^ 5) follows, indicating the number of queries.
Each the next M lines contains a query of three integers a, b, c (1 ≤ a, b, c ≤ N, a, b, c are distinct), which indicates the base stations of the three countries respectively.
 
Output
For each query, you should output three integers in a single line, separated by white spaces, indicating the number of nodes that each country occupies. Note that the order is the same as the country's base station input.
 
题目大意:给一棵n个点的树,每次询问有三个点,问离每个点比另外两个点近的点有多少个。
思路:贴一下官方题解:
——————————————————————————————————————————————————————————————————————————————

本题抽象的题意是给出一棵树,有许多询问,每次询问,给出3个点,问有多少个点,到这三个点的最短距离是递增的。
首先考虑两个点的简单情况,因为是树,有特殊性,任意两点间只有唯一的一条路,找到路的中点,就可以把树分成两部分,其中一部分的点是合法解。
回到本题,问题就变成了两个子树的交集。这个考虑一个子树是否是另一子树的子树即可。用dfs序列来判断即可。
时间复杂度是O(nlogn)

——————————————————————————————————————————————————————————————————————————————
即考虑每一个点,求这个点与另两个点劈开成的两颗子树(或者是整棵树减去一棵子树),这里要用到树上倍增求第k祖先。然后求两个子树的交,这个分类讨论一下即可。
PS:用G++交居然栈溢出了。只好换C++开栈了。
 
 
代码(2781MS):
 #ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:1024000000,1024000000")
#endif // ONLINE_JUDGE #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std; const int MAXV = ;
const int MAXE = ;
const int MAX_LOG = ; int head[MAXV], ecnt;
int to[MAXE], next[MAXE];
int n, m, T; void init() {
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v) {
to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
} int fa[MAX_LOG][MAXV];
int size[MAXV], dep[MAXV]; void dfs(int u, int f, int depth) {
fa[][u] = f; size[u] = ; dep[u] = depth;
for(int p = head[u]; ~p; p = next[p]) {
int v = to[p];
if(v == f) continue;
dfs(v, u, depth + );
size[u] += size[v];
}
} void initfa() {
dfs(, -, );
for(int k = ; k < MAX_LOG - ; ++k) {
for(int u = ; u <= n; ++u) {
if(fa[k][u] == -) fa[k + ][u] = ;
else fa[k + ][u] = fa[k][fa[k][u]];
}
}
} int upslope(int u, int p) {
for(int k = ; k < MAX_LOG; ++k) {
if((p >> k) & ) u = fa[k][u];
}
return u;
} int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
u = upslope(u, dep[u] - dep[v]);
if(u == v) return u;
for(int k = MAX_LOG - ; k >= ; --k) {
if(fa[k][u] != fa[k][v])
u = fa[k][u], v = fa[k][v];
}
return fa[][u];
} struct Node {
int type, r;
Node(int type, int r): type(type), r(r) {}
}; Node get_middle(int a, int b, int ab) {
int len = dep[a] + dep[b] - * dep[ab];
if(dep[a] >= dep[b]) {
return Node(, upslope(a, (len - ) / ));
} else {
return Node(, upslope(b, len / ));
}
} int calc(int a, int b, int c, int ab, int ac) {
Node bn = get_middle(a, b, ab), cn = get_middle(a, c, ac);
if(bn.type == && cn.type == ) {
if(dep[bn.r] < dep[cn.r]) swap(bn, cn);
if(lca(bn.r, cn.r) == cn.r) return size[bn.r];
else return ;
} else if(bn.type == && cn.type == ) {
if(dep[bn.r] < dep[cn.r]) swap(bn, cn);
if(lca(bn.r, cn.r) == cn.r) return n - size[cn.r];
else return n - size[bn.r] - size[cn.r];
} else {
if(bn.type == ) swap(bn, cn);
int t = lca(bn.r, cn.r);
if(t == cn.r) return n - size[cn.r];
if(t == bn.r) return size[bn.r] - size[cn.r];
return size[bn.r];
}
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
init();
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
add_edge(u, v);
}
initfa();
scanf("%d", &m);
for(int i = , a, b, c; i < m; ++i) {
scanf("%d%d%d", &a, &b, &c);
int ab = lca(a, b), ac = lca(a, c), bc = lca(b, c);
printf("%d %d %d\n", calc(a, b, c, ab, ac), calc(b, a, c, ab, bc), calc(c, a, b, ac, bc));
}
}
}

HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)的更多相关文章

  1. HDU 4816 Bathysphere(数学)(2013 Asia Regional Changchun)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816 Problem Description The Bathysphere is a spheric ...

  2. 2013 Asia Regional Changchun C

    Little Tiger vs. Deep Monkey Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K ( ...

  3. 2013 Asia Regional Changchun I 题,HDU(4821),Hash

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4821 解题报告:搞了很久,总算搞出来了,还是参考了一下网上的解法,的确很巧,和上次湘潭的比 ...

  4. 2013 Asia Regional Changchun

    Hard Code http://acm.hdu.edu.cn/showproblem.php?pid=4813 #include<cstdio> ]; int main(){ int t ...

  5. HDU 5444 Elven Postman (2015 ACM/ICPC Asia Regional Changchun Online)

    Elven Postman Elves are very peculiar creatures. As we all know, they can live for a very long time ...

  6. 2015 ACM/ICPC Asia Regional Changchun Online HDU 5444 Elven Postman【二叉排序树的建树和遍历查找】

    Elven Postman Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  7. HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online)

    HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online) 题目链接http://acm.hdu.edu.cn/showp ...

  8. (并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )

    http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others)    Memo ...

  9. (二叉树)Elven Postman -- HDU -- 54444(2015 ACM/ICPC Asia Regional Changchun Online)

    http://acm.hdu.edu.cn/showproblem.php?pid=5444 Elven Postman Time Limit: 1500/1000 MS (Java/Others)  ...

随机推荐

  1. OC文件大小的计算方法,多用于清理缓存

    OC文件大小的计算方法,一般多用于清理缓存.下载.统计 可以使用以下方法: #pragma mark Bt转换 + (NSString *)axcFileSizeWithToString:(unsig ...

  2. 那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)[zz]

    openssl dgst –sign privatekey.pem –sha1 –keyform PEM –c c:\server.pem 将文件用sha1摘要,并用privatekey.pem中的私 ...

  3. 使用Nginx在自己的电脑上实现负载均衡

    我其实早就想弄这个负载均衡了,但是总觉得这玩意肯定不简单,今天星期六闲着没事终于下定决心来搞一搞他了,但是没想到这玩意这么简单,真的是出乎我的意料的简单(我现在陪的是最简单的那种).额是没有我想象中的 ...

  4. linux下时间的修改

    1.关于时间的修改,在linux还是很重要的,在这里只是介绍一个简单的常用的命令,并且时间不会写入到系统. 2.命令 3.如果想把时间写进系统 修改完成之后,输入clock -w 时间将会被写进CMO ...

  5. 原因是未找到“sgen.exe”,或未安装 .NET Framework SDK v2.0

    visual studio编译出现错误:错误 2 任务失败,原因是未找到“sgen.exe”,或未安装 .NET Framework SDK v2.0.该任务正在注册表项 HKEY_LOCAL_MAC ...

  6. Angular自动双向绑定值

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> ...

  7. [LeetCode]题解(python):038-Count and Say

    题目来源 https://leetcode.com/problems/count-and-say/ The count-and-say sequence is the sequence of inte ...

  8. documentElement和ownerDocument和ownerElement

    1.document.documentElement是指文档根节点----HTML元素 2.element.ownerDocument是指当前元素所在的文档对象----document 3.attrO ...

  9. http://blog.csdn.net/jiyiqinlovexx/article/details/38326865

    http://blog.csdn.net/jiyiqinlovexx/article/details/38326865

  10. 浅谈负载均衡SLB、CLB和综合应用

    SLB     服务器负载均衡(Server Load Balancing),可以看作HSRP(热备份路由器协议)的扩展,实现多个服务器之间的负载均衡.     虚拟服务器代表的是多个真实服务器的群集 ...